1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// Copyright (C) 2007 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MULTITHREADED_OBJECT_EXTENSIOn_
#define DLIB_MULTITHREADED_OBJECT_EXTENSIOn_
#include "multithreaded_object_extension_abstract.h"
#include "threads_kernel.h"
#include "auto_mutex_extension.h"
#include "rmutex_extension.h"
#include "rsignaler_extension.h"
#include "../algs.h"
#include "../assert.h"
#include "../map.h"
#include "../member_function_pointer.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class multithreaded_object
{
/*!
INITIAL VALUE
- is_running_ == false
- should_stop_ == false
- thread_ids.size() == 0
- dead_threads.size() == 0
- threads_started == 0
CONVENTION
- number_of_threads_registered() == thread_ids.size() + dead_threads.size()
- number_of_threads_alive() == threads_started
- is_running() == is_running_
- should_stop() == should_stop_
- thread_ids == a map of current thread ids to the member function
pointers that that thread runs.
- threads_started == the number of threads that have been spawned to run
thread_helper but haven't ended yet.
- dead_threads == a queue that contains all the member function pointers
for threads that are currently registered but not running
- m_ == the mutex used to protect all our variables
- s == the signaler for m_
!*/
public:
multithreaded_object (
);
virtual ~multithreaded_object (
) = 0;
void clear (
);
bool is_running (
) const;
unsigned long number_of_threads_alive (
) const;
unsigned long number_of_threads_registered (
) const;
void wait (
) const;
void start (
);
void pause (
);
void stop (
);
protected:
bool should_stop (
) const;
template <
typename T
>
void register_thread (
T& object,
void (T::*thread)()
)
{
auto_mutex M(m_);
try
{
mfp mf;
mf.set(object,thread);
dead_threads.enqueue(mf);
if (is_running_)
start();
}
catch (...)
{
is_running_ = false;
should_stop_ = true;
s.broadcast();
throw;
}
}
private:
class raii_thread_helper
{
public:
raii_thread_helper(multithreaded_object& self_, thread_id_type id_);
~raii_thread_helper();
multithreaded_object& self;
thread_id_type id;
};
void thread_helper(
);
typedef member_function_pointer<> mfp;
rmutex m_;
rsignaler s;
map<thread_id_type,mfp,memory_manager<char>::kernel_2a>::kernel_1a thread_ids;
queue<mfp,memory_manager<char>::kernel_2a>::kernel_1a dead_threads;
bool is_running_;
bool should_stop_;
unsigned long threads_started;
// restricted functions
multithreaded_object(multithreaded_object&); // copy constructor
multithreaded_object& operator=(multithreaded_object&); // assignment operator
};
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "multithreaded_object_extension.cpp"
#endif
#endif // DLIB_MULTITHREADED_OBJECT_EXTENSIOn_
|