| |
| /pliant/language/schedule/resourcesem.pli |
| |
| 1 |
# Copyright Hubert Tonneau hubert.tonneau@pliant.cx | |
| 2 |
# | |
| 3 |
# This program is free software; you can redistribute it and/or | |
| 4 |
# modify it under the terms of the GNU General Public License version 2 | |
| 5 |
# as published by the Free Software Foundation. | |
| 6 |
# | |
| 7 |
# This program is distributed in the hope that it will be useful, | |
| 8 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 9 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 10 |
# GNU General Public License for more details. | |
| 11 |
# | |
| 12 |
# You should have received a copy of the GNU General Public License | |
| 13 |
# version 2 along with this program; if not, write to the Free Software | |
| 14 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 15 |
| |
| 16 |
module "/pliant/language/unsafe.pli" | |
| 17 |
module "/pliant/language/os.pli" | |
| 18 |
module "/pliant/language/schedule/threads_engine.pli" | |
| 19 |
| |
| 20 |
constant busy_wait false # processor_count>1 | |
| 21 |
| |
| 22 |
| |
| 23 |
if busy_wait | |
| 24 |
function wait_a_bit | |
| 25 |
for (var Int i) 0 10 | |
| 26 |
void | |
| 27 |
else | |
| 28 |
function wait_a_bit | |
| 29 |
os_yield | |
| 30 |
| |
| 31 |
| |
| 32 |
type ResourceSem | |
| 33 |
field Int current | |
| 34 |
field Int maxi | |
| 35 |
field ThreadQueue queue | |
| 36 |
| |
| 37 |
| |
| 38 |
function build sem | |
| 39 |
arg_w ResourceSem sem | |
| 40 |
sem current := 0 | |
| 41 |
sem maxi := 1 | |
| 42 |
| |
| 43 |
method sem safe_read_current -> c | |
| 44 |
arg_rw ResourceSem sem ; arg Int c | |
| 45 |
part read | |
| 46 |
c := atomic_read_and_set sem:current undefined | |
| 47 |
if c=undefined | |
| 48 |
wait_a_bit | |
| 49 |
restart read | |
| 50 |
| |
| 51 |
| |
| 52 |
method s configure maxi | |
| 53 |
arg_rw ResourceSem s ; arg Int maxi | |
| 54 |
s maxi := maxi | |
| 55 |
| |
| 56 |
method s query current maxi | |
| 57 |
arg_rw ResourceSem s ; arg_w Int current maxi | |
| 58 |
part read | |
| 59 |
current := s current | |
| 60 |
if current=undefined | |
| 61 |
restart read | |
| 62 |
maxi := s maxi | |
| 63 |
| |
| 64 |
| |
| 65 |
method sem request n | |
| 66 |
arg_rw ResourceSem sem ; arg Int n | |
| 67 |
var Int c := sem safe_read_current | |
| 68 |
if (c<>0 and c+n>sem:maxi) or not sem:queue:is_empty | |
| 69 |
part wait | |
| 70 |
sem:queue add_current_thread 0 n | |
| 71 |
sem current := c | |
| 72 |
stop_current_thread | |
| 73 |
c := sem safe_read_current | |
| 74 |
if c<>0 and c+n>sem:maxi | |
| 75 |
restart wait | |
| 76 |
sem current := c+n | |
| 77 |
| |
| 78 |
| |
| 79 |
method sem release n | |
| 80 |
arg_rw ResourceSem sem ; arg Int n | |
| 81 |
var uInt c := sem safe_read_current | |
| 82 |
sem:queue restart_some_threads sem:maxi-(c-n) ((addressof sem:current) map uInt) (cast c-n uInt) | |
| 83 |
| |
| 84 |
| |
| 85 |
method sem nowait_request n -> success | |
| 86 |
arg_rw ResourceSem sem ; arg Int n ; arg CBool success | |
| 87 |
var Int c := sem safe_read_current | |
| 88 |
if c+n<=sem:maxi and sem:queue:is_empty | |
| 89 |
sem current := c+n | |
| 90 |
success := true | |
| 91 |
else | |
| 92 |
sem current := c | |
| 93 |
success := false | |
| 94 |
| |
| 95 |
| |
| 96 |
export ResourceSem '. configure' '. query' | |
| 97 |
export '. request' '. release' '. nowait_request' | |
| |