this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 *
6 * Copyright:
7 * Christian Schulte, 2009
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <gecode/support.hh>
35
36namespace Gecode { namespace Support {
37
38 /*
39 * Threads
40 */
41
42 Mutex* Thread::m(void) {
43 static Mutex* m = new Mutex;
44 return m;
45 }
46
47 Thread::Run* Thread::idle = nullptr;
48
49 void
50 Thread::Run::exec(void) {
51 while (true) {
52 // Execute runnable
53 {
54 Runnable* e;
55 m.acquire();
56 GECODE_ASSUME(r != nullptr);
57 e=r; r=nullptr;
58 m.release();
59 assert(e != nullptr);
60 e->run();
61 if (e->todelete()) {
62 Terminator* t = e->terminator();
63 delete e;
64 if (t)
65 t->terminated();
66 }
67 }
68 // Put into idle stack
69 Thread::m()->acquire();
70 n=Thread::idle; Thread::idle=this;
71 Thread::m()->release();
72 // Wait for next runnable
73 e.wait();
74 }
75 }
76
77 namespace {
78
79 class GlobalMutexRunnable : public Runnable {
80 protected:
81 Mutex _m;
82 Mutex _m_write;
83 Event _e;
84 Event _e_done;
85 Mutex* _to_acquire;
86 Mutex* _to_release;
87 public:
88 GlobalMutexRunnable(void) : _to_acquire(nullptr), _to_release(nullptr) {}
89 virtual void run(void) {
90 while (true) {
91 _m.acquire();
92 if (_to_acquire) {
93 _to_acquire->acquire();
94 _to_acquire = nullptr;
95 _e_done.signal();
96 } else if (_to_release) {
97 _to_release->release();
98 _to_release = nullptr;
99 _e_done.signal();
100 }
101 _m.release();
102 _e.wait();
103 }
104 }
105 void acquire(Mutex* m) {
106 _m_write.acquire();
107 _m.acquire();
108 _to_acquire = m;
109 _m.release();
110 _e.signal();
111 _e_done.wait();
112 _m_write.release();
113 }
114 void release(Mutex* m) {
115 _m_write.acquire();
116 _m.acquire();
117 _to_release = m;
118 _m.release();
119 _e.signal();
120 _e_done.wait();
121 _m_write.release();
122 }
123 };
124
125 class GlobalMutexRunnableInit {
126 public:
127 GlobalMutexRunnable* gmr;
128 GlobalMutexRunnableInit(void) : gmr(new GlobalMutexRunnable) {
129 Thread::run(gmr);
130 }
131 };
132
133 GlobalMutexRunnable&
134 globalMutexRunnable(void) {
135 static GlobalMutexRunnableInit gmri;
136 return *gmri.gmr;
137 }
138 }
139
140 void
141 Thread::acquireGlobalMutex(Mutex* m) {
142 globalMutexRunnable().acquire(m);
143 }
144
145 void
146 Thread::releaseGlobalMutex(Mutex* m) {
147 globalMutexRunnable().release(m);
148 }
149
150}}
151
152// STATISTICS: support-any