Skip to content

Commit

Permalink
- Added the ability to use custom containers inside the channel objec…
Browse files Browse the repository at this point in the history
…t. Please check out the comments to get an idea which constraints have to be fulfilled.

- Added an example that uses copied Channel-shared-ptr-objects.
  • Loading branch information
DorianGrey committed Aug 23, 2012
1 parent 64637a2 commit 43f7f29
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 8 deletions.
23 changes: 17 additions & 6 deletions Channel/Channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,18 @@
/** \brief This is the basic channel class. It provides an internal message-queue and a stream-like
* message add/remove.
* \param MsgType Type of the messages that are exchanged between the communications partners.
* \param Storage Possibly custom container class. Due to some STL restrictions, I cannot use a
* template template parameter effectively here. Thus, if the default container should be
* changed, you always have to give the whole container definition, like
* Channel<std::string, std::priority_queue<std::string>> .
* Note that any container you use has to implement either the queue policy (here: push(T),
* pop(), front(), empty() ) directly or has to adopt the queue internals, like shown in
* http://www.cplusplus.com/reference/stl/queue/ .
* I.e., by default, deque and list are implementing this, like
* template < class T, class Container = std::deque<T> > class queue
* template < class T, class Container = std::list<T> > class queue .
*/
template<typename MsgType>
template<typename MsgType, typename Storage = std::queue<MsgType>>
class Channel
{
public:
Expand Down Expand Up @@ -163,7 +173,7 @@ class Channel
std::mutex __accessMutex;
std::condition_variable __waitCondition;

std::queue<MsgType> __msgQueue;
Storage __msgQueue;
};

/** \brief This is the channel helper class. Since a channel is regularly used in different threads,
Expand All @@ -174,7 +184,7 @@ class Channel
* does not have any additional data members. *
* \param MsgType Type of the messages that are exchanged between the communications partners.
*/
template<typename MsgType>
template<typename MsgType, typename Storage = std::queue<MsgType>>
struct Chan
{
Chan(): __me(std::make_shared<Channel<MsgType>>()) {}
Expand Down Expand Up @@ -203,7 +213,7 @@ struct Chan
return *__me > destination;
}
private:
std::shared_ptr<Channel<MsgType>> __me;
std::shared_ptr<Channel<MsgType, Storage>> __me;
};

/** \brief Helper function to automatically create channel-objects that are managed by shared_ptr objects.
Expand All @@ -212,9 +222,10 @@ struct Chan
* \return Chan<U> Channel using type U, managed by the wrapper struct Chan<>.
*
*/
template<typename U> inline Chan<U> make_chan()
template<typename MsgType, typename Storage = std::queue<MsgType>>
inline Chan<MsgType, Storage> make_chan()
{
return Chan<U>();
return Chan<MsgType, Storage>();
}

#endif
50 changes: 48 additions & 2 deletions Example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void Example1(std::uint32_t numRuns)
std::thread t1([&chan, numRuns, &coutmutex]() -> void
{
std::uint32_t runs = numRuns;
float msgBase = 5.0f;
float msgBase = 5.1f;
while (runs-- > 0)
{
chan << msgBase;
Expand Down Expand Up @@ -89,13 +89,59 @@ void Example2(std::uint32_t numRuns)
t2.join();
}

/**
Example 3: Create a shared-ptr-channel, handle it over to two threads, and go ahead.
*/
static std::mutex example3_mutex;

void Example3_Task1(Chan<double> channel, std::uint32_t numRuns)
{
double msgBase = 5.3;
while (numRuns-- > 0)
{
channel << msgBase;
msgBase += 1.0;
std::lock_guard<std::mutex> guard(example3_mutex);
std::cout << "Task 1 put a msg." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void Example3_Task2(Chan<double> channel, std::uint32_t numRuns)
{
double res = 0.0;
while (numRuns-- > 0)
{
channel >> res;
std::lock_guard<std::mutex> guard(example3_mutex);
std::cout << "Task 2 took a msg: " << res << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}

void Example3(std::uint32_t numRuns)
{
auto chan = make_chan<double>();
std::thread t1(Example3_Task1, chan, numRuns);
std::thread t2(Example3_Task2, chan, numRuns);
t1.join();
t2.join();
}

int main()
{
// Running test 1
std::cout << "[Test 1] Directly instantiating channel... " << std::endl;
Example1(10);
std::cout << "[Test 1] Completed. " << std::endl;
std::cout << "[Test 2] Instantiating channel using make_channel and wrapper-struct... " << std::endl;

// Running test 2
std::cout << "[Test 2] Instantiating channel using make_chan and wrapper-struct... " << std::endl;
Example2(10);
std::cout << "[Test 2] Completed. " << std::endl;

// Running test 3
std::cout << "[Test 3] Instantiating channel and copy by default... " << std::endl;
Example3(10);
std::cout << "[Test 3] Completed. " << std::endl;
return 0;
}

0 comments on commit 43f7f29

Please sign in to comment.