mirror of
https://github.com/davisking/dlib.git
synced 2024-11-01 10:14:53 +08:00
Added an example for the type_safe_union object.
--HG-- extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402808
This commit is contained in:
parent
ae53881116
commit
6c528a2020
@ -48,6 +48,7 @@ add_example(member_function_pointer_ex)
|
||||
add_example(mlp_ex)
|
||||
add_example(multithreaded_object_ex)
|
||||
add_example(pipe_ex)
|
||||
add_example(pipe_ex_2)
|
||||
add_example(quantum_computing_ex)
|
||||
add_example(queue_ex)
|
||||
add_example(rank_features_ex)
|
||||
|
157
examples/pipe_ex_2.cpp
Normal file
157
examples/pipe_ex_2.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
|
||||
|
||||
/*
|
||||
This is an example showing how to use the type_safe_union and pipe object from
|
||||
from the dlib C++ Library to send messages between threads.
|
||||
|
||||
In this example we will create a class with a single thread in it. This thread
|
||||
will receive messages from a pipe object and simply print them to the screen.
|
||||
The interesting thing about this example is that it shows how to use a pipe and
|
||||
type_safe_union to create a message channel between threads that can send many
|
||||
different types of objects in a type safe manner.
|
||||
|
||||
|
||||
|
||||
Program output:
|
||||
got a float: 4.567
|
||||
got a string: string message
|
||||
got an int: 7
|
||||
got a string: yet another string message
|
||||
*/
|
||||
|
||||
|
||||
#include "dlib/threads.h"
|
||||
#include "dlib/pipe.h"
|
||||
#include "dlib/type_safe_union.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace dlib;
|
||||
using namespace std;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
typedef type_safe_union<int, float, std::string> tsu_type;
|
||||
/* This is a typedef for the type_safe_union we will be using in this example.
|
||||
This type_safe_union object is a type-safe analogue of a union declared as follows:
|
||||
union our_union_type
|
||||
{
|
||||
int a;
|
||||
float b;
|
||||
std::string c;
|
||||
};
|
||||
|
||||
Note that the above union isn't actually valid C++ code because it contains a
|
||||
non-POD type. That is, you can't put a std::string or any non-trivial
|
||||
C++ class in a union. The type_safe_union, however, enables you to store non-POD
|
||||
types such as the std::string.
|
||||
|
||||
*/
|
||||
|
||||
// And here we have a typedef for the pipe we will be using
|
||||
typedef dlib::pipe<tsu_type>::kernel_1a pipe_type;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class pipe_example : private threaded_object
|
||||
{
|
||||
public:
|
||||
pipe_example(
|
||||
) :
|
||||
message_pipe(4) // This 4 here is the size of our message_pipe. The significance is that
|
||||
// if you try to enqueue more than 4 messages onto the pipe then enqueue() will
|
||||
// block until there is room.
|
||||
{
|
||||
// start the thread
|
||||
start();
|
||||
}
|
||||
|
||||
~pipe_example (
|
||||
)
|
||||
{
|
||||
// wait for all the messages to be processed
|
||||
message_pipe.wait_until_empty();
|
||||
|
||||
// Now disable the message_pipe. Doing this will cause all calls to
|
||||
// message_pipe.dequeue() to return false so our threads will terminate
|
||||
message_pipe.disable();
|
||||
|
||||
// now block until all the threads have terminated
|
||||
wait();
|
||||
}
|
||||
|
||||
// Here we declare our pipe object. It will contain our messages.
|
||||
// There are only two requirements on the type of objects you can use in a
|
||||
// pipe, first they must have a default constructor and second they must
|
||||
// be swappable by a global swap().
|
||||
pipe_type message_pipe;
|
||||
|
||||
|
||||
// When we call apply_to_contents() below these are the
|
||||
// functions which get called.
|
||||
void operator() (int val)
|
||||
{
|
||||
cout << "got an int: " << val << endl;
|
||||
}
|
||||
|
||||
void operator() (float val)
|
||||
{
|
||||
cout << "got a float: " << val << endl;
|
||||
}
|
||||
|
||||
void operator() (std::string val)
|
||||
{
|
||||
cout << "got a string: " << val << endl;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void thread ()
|
||||
{
|
||||
tsu_type msg;
|
||||
|
||||
// Here we loop on messages from the message_pipe.
|
||||
while (message_pipe.dequeue(msg))
|
||||
{
|
||||
// Tell the msg type_safe_union object to take whatever object
|
||||
// it contains and call (*this)(contained_object); So what
|
||||
// happens here is one of the three above functions gets called
|
||||
// with the message we just got.
|
||||
msg.apply_to_contents(*this);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
int main()
|
||||
{
|
||||
pipe_example pe;
|
||||
|
||||
// Make one of our type_safe_union objects
|
||||
tsu_type msg;
|
||||
|
||||
// Treat our msg as a float and assign it 4.567
|
||||
msg.get<float>() = 4.567;
|
||||
// Now put the message into the pipe
|
||||
pe.message_pipe.enqueue(msg);
|
||||
|
||||
// Put a string into the pipe
|
||||
msg.get<std::string>() = "string message";
|
||||
pe.message_pipe.enqueue(msg);
|
||||
|
||||
// And now an int
|
||||
msg.get<int>() = 7;
|
||||
pe.message_pipe.enqueue(msg);
|
||||
|
||||
// And another string
|
||||
msg.get<std::string>() = "yet another string message";
|
||||
pe.message_pipe.enqueue(msg);
|
||||
|
||||
|
||||
// the main function won't really terminate here. It will call the destructor for pe
|
||||
// which will block until all the messages have been processed.
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user