Skip to content

Commit

Permalink
Merge branch 'feature/ISSUE3-RemoveBoostDep'
Browse files Browse the repository at this point in the history
* feature/ISSUE3-RemoveBoostDep:
  Changed version from "0.1" to "0.1.0" in configure.ac.
  Added AM_CONDITIONAL BUILD_BOOST_FROM_TARBALL.  Specifying a Boost tarball at config time is now unnecessary.
  - Added condition var notify_all()'s to the wait_push()'s.
  - Added implementation of sync_queue<>. - Implemented sync_queue_impl_selector.h, which selects at compile time between this sync_queue<> and Boost's sync_queue<>.  Pulls the latter into the global namespace. - Replaced explicit uses of boost::concurrency::sync_queue with undecorated sync_queue.
  • Loading branch information
gvansickle committed Oct 11, 2015
2 parents b9033ba + 75d004f commit 5bbc044
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 26 deletions.
3 changes: 3 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ dist_doc_DATA=README.md
bin_PROGRAMS=ucg
ucg_SOURCES=main.cpp

if BUILD_BOOST_FROM_TARBALL
# Collect all the Boost libraries we need into a single variable.
BOOST_LOCAL_LIB = $(top_builddir)/third_party/$(BOOST_TARBALL_DIRNAME)/stage/lib
ALLBOOSTLIBS = $(BOOST_LOCAL_LIB)/libboost_thread.a \
$(BOOST_LOCAL_LIB)/libboost_system.a
endif

ucg_CPPFLAGS = -I $(top_srcdir)/src \
$(BOOST_TR1_CPPFLAGS) $(BOOST_CPPFLAGS) \
Expand All @@ -46,3 +48,4 @@ ucg_CXXFLAGS = $(AM_CXXFLAGS)
ucg_LDFLAGS = $(BOOST_LIBTOOL_FLAGS) $(BOOST_LDFLAGS) \
$(AM_LDFLAGS)
ucg_LDADD = ./src/libsrc.a $(ALLBOOSTLIBS)

4 changes: 3 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
dnl Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([UniversalCodeGrep], [0.1], [https://github.com/gvansickle/ucg/issues],,[https://github.com/gvansickle/ucg])
AC_INIT([UniversalCodeGrep], [0.1.0], [https://github.com/gvansickle/ucg/issues],,[https://github.com/gvansickle/ucg])

AC_CONFIG_SRCDIR([src/Globber.cpp])
AC_CONFIG_HEADERS([config.h])
Expand Down Expand Up @@ -104,6 +104,7 @@ AM_MISSING_PROG([AUTOM4TE], [autom4te])
# even though it's correctly using the headers in /usr/local/include.
GRVS_ARG_WITH_FILE([FILE_PATH_BOOST_SOURCE_TARBALL], [boost-tarball], [boost source distribution tarball],
[],[AC_MSG_WARN([No Boost source tarball specified.])])
AM_CONDITIONAL([BUILD_BOOST_FROM_TARBALL],[test -f "$FILE_PATH_BOOST_SOURCE_TARBALL"])

# The list of Boost libraries we need, in a form that Boost's bootstrap.sh can understand.
AC_SUBST([REQUIRED_BOOST_LIBS],[system,thread])
Expand Down Expand Up @@ -197,6 +198,7 @@ gcc < 4.9.0 is known to have this problem.])]
CXXFLAGS="$SAVE_CXXFLAGS"
AC_LANG_POP([C++])


###
### Checks for system services
###
Expand Down
11 changes: 5 additions & 6 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
#include <vector>
#include <thread>
#include <utility>
#include <boost/thread/sync_queue.hpp>

#include "sync_queue_impl_selector.h"

#include "ArgParse.h"
#include "Globber.h"
Expand All @@ -32,9 +33,9 @@
#include "OutputTask.h"



int main(int argc, char **argv)
{
// We'll keep the scanner threads in this vector so we can join() them later.
std::vector<std::thread> scanner_threads;

TypeManager tm;
Expand All @@ -49,8 +50,8 @@ int main(int argc, char **argv)
std::clog << "Num jobs: " << ap.m_jobs << std::endl;

// Create the queues.
boost::concurrent::sync_queue<std::string> q;
boost::concurrent::sync_queue<MatchList> out_q;
sync_queue<std::string> q;
sync_queue<MatchList> out_q;

// Set up the globber.
Globber g(ap.m_paths, tm, q);
Expand All @@ -63,8 +64,6 @@ int main(int argc, char **argv)
// Start the output task thread.
std::thread ot {&OutputTask::Run, &output_task};



// Start the scanner threads.
FileScanner fs(q, out_q, ap.m_pattern, ap.m_ignore_case);
for(int t=0; t<ap.m_jobs; ++t)
Expand Down
8 changes: 5 additions & 3 deletions src/FileScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@

#include "config.h"

#include <iostream>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <regex>
#include <thread>
Expand All @@ -35,8 +37,8 @@

static std::mutex f_assign_affinity_mutex;

FileScanner::FileScanner(boost::concurrent::sync_queue<std::string> &in_queue,
boost::concurrent::sync_queue<MatchList> &output_queue,
FileScanner::FileScanner(sync_queue<std::string> &in_queue,
sync_queue<MatchList> &output_queue,
std::string regex,
bool ignore_case) : m_in_queue(in_queue), m_output_queue(output_queue), m_regex(regex), m_ignore_case(ignore_case),
m_next_core(0), m_use_mmap(false), m_manually_assign_cores(false)
Expand All @@ -62,7 +64,7 @@ void FileScanner::Run()
std::regex_constants::ECMAScript | static_cast<typeof(std::regex_constants::icase)>(std::regex_constants::icase * m_ignore_case));

std::string next_string;
while(m_in_queue.wait_pull(next_string) != boost::concurrent::queue_op_status::closed)
while(m_in_queue.wait_pull(next_string) != queue_op_status::closed)
{
MatchList ml(next_string);

Expand Down
10 changes: 5 additions & 5 deletions src/FileScanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@


#include <string>
#include <boost/thread/sync_queue.hpp>

#include "sync_queue_impl_selector.h"
#include "MatchList.h"

/**
Expand All @@ -32,8 +32,8 @@
class FileScanner
{
public:
FileScanner(boost::concurrent::sync_queue<std::string> &in_queue,
boost::concurrent::sync_queue<MatchList> &output_queue,
FileScanner(sync_queue<std::string> &in_queue,
sync_queue<MatchList> &output_queue,
std::string regex,
bool ignore_case);
virtual ~FileScanner();
Expand Down Expand Up @@ -71,9 +71,9 @@ class FileScanner
*/
void FreeFile(const char * file_data, size_t file_size);

boost::concurrent::sync_queue<std::string>& m_in_queue;
sync_queue<std::string>& m_in_queue;

boost::concurrent::sync_queue<MatchList> &m_output_queue;
sync_queue<MatchList> &m_output_queue;

std::string m_regex;

Expand Down
2 changes: 1 addition & 1 deletion src/Globber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

Globber::Globber(std::vector<std::string> start_paths,
TypeManager &type_manager,
boost::concurrent::sync_queue<std::string>& out_queue)
sync_queue<std::string>& out_queue)
: m_start_paths(start_paths),
m_out_queue(out_queue),
m_type_manager(type_manager)
Expand Down
9 changes: 6 additions & 3 deletions src/Globber.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
#define GLOBBER_H_


#include <vector>
#include <string>
#include <thread>
#include <boost/thread/sync_queue.hpp>

#include "sync_queue_impl_selector.h"

class TypeManager;

Expand All @@ -33,14 +35,15 @@ class TypeManager;
class Globber
{
public:
Globber(std::vector<std::string> start_paths, TypeManager &type_manager, boost::concurrent::sync_queue<std::string> &out_queue);
Globber(std::vector<std::string> start_paths, TypeManager &type_manager, sync_queue<std::string> &out_queue);
virtual ~Globber();

void Run();

private:
std::vector<std::string> m_start_paths;
boost::concurrent::sync_queue<std::string>& m_out_queue;

sync_queue<std::string>& m_out_queue;

TypeManager &m_type_manager;
};
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ libsrc_a_SOURCES = \
MatchList.cpp MatchList.h \
FileScanner.cpp FileScanner.h \
OutputTask.cpp OutputTask.h \
sync_queue.h \
sync_queue_impl_selector.h \
TypeManager.cpp TypeManager.h

libsrc_a_CPPFLAGS = $(AM_CPPFLAGS)
Expand Down
4 changes: 2 additions & 2 deletions src/OutputTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <unistd.h>
#include <stdio.h>

OutputTask::OutputTask(bool enable_color, boost::concurrent::sync_queue<MatchList> &input_queue)
OutputTask::OutputTask(bool enable_color, sync_queue<MatchList> &input_queue)
: m_input_queue(input_queue), m_enable_color(enable_color)
{
m_output_is_tty = isatty(fileno(stdout));
Expand All @@ -37,7 +37,7 @@ void OutputTask::Run()
{
MatchList ml;

while(m_input_queue.wait_pull(ml) != boost::concurrent::queue_op_status::closed)
while(m_input_queue.wait_pull(ml) != queue_op_status::closed)
{
ml.Print(m_output_is_tty, m_enable_color);
}
Expand Down
7 changes: 4 additions & 3 deletions src/OutputTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,23 @@
#define OUTPUTTASK_H_

#include <MatchList.h>
#include <boost/thread/sync_queue.hpp>

#include "sync_queue_impl_selector.h"

/*
*
*/
class OutputTask
{
public:
OutputTask(bool enable_color, boost::concurrent::sync_queue<MatchList> &input_queue);
OutputTask(bool enable_color, sync_queue<MatchList> &input_queue);
virtual ~OutputTask();

void Run();

private:

boost::concurrent::sync_queue<MatchList> &m_input_queue;
sync_queue<MatchList> &m_input_queue;

bool m_output_is_tty;

Expand Down
144 changes: 144 additions & 0 deletions src/sync_queue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright 2015 Gary R. Van Sickle (grvs@users.sourceforge.net).
*
* This file is part of UltimateCodeSearch.
*
* UltimateCodeSearch is free software: you can redistribute it and/or modify it under the
* terms of version 3 of the GNU General Public License as published by the Free
* Software Foundation.
*
* UltimateCodeSearch is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* UltimateCodeSearch. If not, see <http://www.gnu.org/licenses/>.
*/

/** @file */

#ifndef SYNC_QUEUE_H_
#define SYNC_QUEUE_H_

#include <mutex>
#include <condition_variable>
#include <queue>


enum class queue_op_status
{
success,
empty,
full,
closed,
busy,
timeout,
not_ready
};

/**
* Simple unbounded synchronized queue class.
*
* The interface implemented here is compatible with Boost's sync_queue<> implementation
* documented here: http://www.boost.org/doc/libs/1_59_0/doc/html/thread/sds.html#thread.sds.synchronized_queues.
*/
template <typename ValueType>
class sync_queue
{
public:
sync_queue() : m_closed(false) {};
~sync_queue() {};

void close()
{
std::lock_guard<std::mutex> lock(m_mutex);

m_closed = true;

// Notify any threads waiting on the queue's condition variable that it's just been closed.
m_cv.notify_all();
}

queue_op_status wait_push(const ValueType& x)
{
std::lock_guard<std::mutex> lock(m_mutex);

// Is the queue closed?
if(m_closed)
{
// Yes, fail the push.
return queue_op_status::closed;
}

// Push via copy.
m_underlying_queue.push(x);

// Notify any threads waiting on the queue's condition variable that it now has something to pull.
m_cv.notify_all();

return queue_op_status::success;
}

queue_op_status wait_push(const ValueType&& x)
{
std::lock_guard<std::mutex> lock(m_mutex);

// Is the queue closed?
if(m_closed)
{
// Yes, fail the push.
return queue_op_status::closed;
}

// Push via move.
m_underlying_queue.push(std::move(x));

// Notify any threads waiting on the queue's condition variable that it now has something to pull.
m_cv.notify_all();

return queue_op_status::success;
}

queue_op_status wait_pull(ValueType& x)
{
// Using a unique_lock<> here vs. a lock_guard<> because we'll be using a condition variable, which needs
// to unlock the mutex.
std::unique_lock<std::mutex> lock(m_mutex);

if(m_underlying_queue.empty() && m_closed)
{
// Queue is empty and has been closed, let the caller know.
return queue_op_status::closed;
}

// Wait until the queue is not empty, or somebody closes the sync_queue<>.
m_cv.wait(lock, [this](){ return !m_underlying_queue.empty() || m_closed; });

// Check if we've be awoken to a closed and empty queue.
if(m_underlying_queue.empty() && m_closed)
{
// We have, let the caller know.
return queue_op_status::closed;
}

// Otherwise, we have something in the queue to pull off.
// Use move-assignment vs. copy-assignment for efficiency.
x = std::move(m_underlying_queue.front());
m_underlying_queue.pop();

return queue_op_status::success;
}

private:

std::mutex m_mutex;

std::condition_variable m_cv;

bool m_closed;

std::queue<ValueType> m_underlying_queue;

};

#endif /* SYNC_QUEUE_H_ */
Loading

0 comments on commit 5bbc044

Please sign in to comment.