Generated on for Gecode by doxygen 1.15.0
thread.cpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.dev>
5 *
6 * Contributing authors:
7 * Mikael Zayenz Lagerkvist <lagerkvist@gecode.dev>
8 *
9 * Copyright:
10 * Christian Schulte, 2009
11 * Mikael Zayenz Lagerkvist, 2026
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.dev
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining
18 * a copy of this software and associated documentation files (the
19 * "Software"), to deal in the Software without restriction, including
20 * without limitation the rights to use, copy, modify, merge, publish,
21 * distribute, sublicense, and/or sell copies of the Software, and to
22 * permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be
26 * included in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 *
36 */
37
38#include <gecode/support.hh>
39
40namespace Gecode { namespace Support {
41
42 /*
43 * Threads
44 */
45
47 static Mutex* m = new Mutex;
48 return m;
49 }
50
51 Thread::Run* Thread::idle = nullptr;
52
53 void
55 while (true) {
56 // Execute runnable
57 {
58 GECODE_ASSUME(r != nullptr);
59 Runnable* e = r.exchange(nullptr);
60 assert(e != nullptr);
61 e->run();
62 const bool delete_after_run = e->todelete();
63 Terminator* t = e->terminator();
64 if (delete_after_run) {
65 delete e;
66 }
67 if (t)
68 t->terminated();
69 }
70 // Put into idle stack
71 Thread::m()->acquire();
73 Thread::m()->release();
74 // Wait for next runnable
75 e.wait();
76 }
77 }
78
80#ifdef GECODE_HAS_THREADS
81 r.store(r0);
82 std::thread t([](Thread::Run* r){r->exec();}, this);
83 t.detach();
84#else
85 throw OperatingSystemError("Thread::run[Threads not supported]");
86#endif
87 }
88
89
90 namespace {
91
92 class GlobalMutexRunnable : public Runnable {
93 protected:
94 Mutex _m;
95 Mutex _m_write;
96 Event _e;
97 Event _e_done;
98 Mutex* _to_acquire;
99 Mutex* _to_release;
100 public:
101 GlobalMutexRunnable(void) : _to_acquire(nullptr), _to_release(nullptr) {}
102 virtual void run(void) {
103 while (true) {
104 _m.acquire();
105 if (_to_acquire) {
106 _to_acquire->acquire();
107 _to_acquire = nullptr;
108 _e_done.signal();
109 } else if (_to_release) {
110 _to_release->release();
111 _to_release = nullptr;
112 _e_done.signal();
113 }
114 _m.release();
115 _e.wait();
116 }
117 }
118 void acquire(Mutex* m) {
119 _m_write.acquire();
120 _m.acquire();
121 _to_acquire = m;
122 _m.release();
123 _e.signal();
124 _e_done.wait();
125 _m_write.release();
126 }
127 void release(Mutex* m) {
128 _m_write.acquire();
129 _m.acquire();
130 _to_release = m;
131 _m.release();
132 _e.signal();
133 _e_done.wait();
134 _m_write.release();
135 }
136 };
137
138 class GlobalMutexRunnableInit {
139 public:
140 GlobalMutexRunnable* gmr;
141 GlobalMutexRunnableInit(void) : gmr(new GlobalMutexRunnable) {
142 Thread::run(gmr);
143 }
144 };
145
146 GlobalMutexRunnable&
147 globalMutexRunnable(void) {
148 static GlobalMutexRunnableInit gmri;
149 return *gmri.gmr;
150 }
151 }
152
153 void
155 globalMutexRunnable().acquire(m);
156 }
157
158 void
160 globalMutexRunnable().release(m);
161 }
162
163}}
164
165// STATISTICS: support-any
Exception: operating system error
Definition exception.hpp:75
An event for synchronization.
Definition thread.hpp:138
void wait(void)
Wait until the event becomes signalled.
Definition thread.hpp:143
void signal(void)
Signal the event.
Definition thread.hpp:133
A mutex for mutual exclausion among several threads.
Definition thread.hpp:78
void release(void)
Release the mutex.
Definition thread.hpp:94
void acquire(void)
Acquire the mutex and possibly block.
Definition thread.hpp:70
An interface for objects that can be run by a thread.
Definition thread.hpp:181
An interface for objects that can be called after a thread has terminated (after running the thread's...
Definition thread.hpp:168
virtual void terminated(void)=0
The function that is called when the thread has terminated.
void exec(void)
Infinite loop for execution.
Definition thread.cpp:54
Event e
Event to wait for next runnable object to execute.
Definition thread.hpp:223
Run * n
Next idle thread.
Definition thread.hpp:219
std::atomic< Runnable * > r
Runnable object to execute.
Definition thread.hpp:221
Run(Runnable *r)
Create a new thread.
Definition thread.cpp:79
static void releaseGlobalMutex(Mutex *m)
release globally acquired mutex m
Definition thread.cpp:159
static Run * idle
Idle runners.
Definition thread.hpp:238
static void acquireGlobalMutex(Mutex *m)
acquire mutex m globally and possibly lock
Definition thread.cpp:154
static Mutex * m(void)
Mutex for synchronization.
Definition thread.cpp:46
Support algorithms and datastructures
Gecode toplevel namespace
Multi _e(Gecode::IntArgs({4, 2, 3, 1}))
#define GECODE_ASSUME(p)
Assert certain property.
Definition macros.hpp:114