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
154
// 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 "../threads.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<>::kernel_1a_c 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_