September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,56 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var fmt = log.New(os.Stdout, "", 0)
|
||||
|
||||
func main() {
|
||||
// three operations per task description
|
||||
acquire := make(chan int)
|
||||
release := make(chan int)
|
||||
count := make(chan chan int)
|
||||
|
||||
// library analogy per WP article
|
||||
go librarian(acquire, release, count, 10)
|
||||
nStudents := 20
|
||||
var studied sync.WaitGroup
|
||||
studied.Add(nStudents)
|
||||
for i := 0; i < nStudents; i++ {
|
||||
go student(acquire, release, count, &studied)
|
||||
}
|
||||
// wait until all students have studied before terminating program
|
||||
studied.Wait()
|
||||
}
|
||||
|
||||
func librarian(a, r chan int, c chan chan int, count int) {
|
||||
p := a // acquire operation is served or not depending on count
|
||||
for {
|
||||
select {
|
||||
case <-p: // acquire/p/wait operation
|
||||
count--
|
||||
if count == 0 {
|
||||
p = nil
|
||||
}
|
||||
case <-r: // release/v operation
|
||||
count++
|
||||
p = a
|
||||
case cc := <-c: // count operation
|
||||
cc <- count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func student(a, r chan int, c chan chan int, studied *sync.WaitGroup) {
|
||||
cc := make(chan int)
|
||||
a <- 0 // acquire
|
||||
c <- cc // request count
|
||||
fmt.Printf("Room entered. Count is %d. Studying...\n", <-cc)
|
||||
time.Sleep(2 * time.Second) // sleep per task description
|
||||
r <- 0 // release
|
||||
studied.Done() // signal done
|
||||
}
|
||||
69
Task/Metered-concurrency/Phix/metered-concurrency.phix
Normal file
69
Task/Metered-concurrency/Phix/metered-concurrency.phix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
sequence sems = {}
|
||||
constant COUNTER = 1, QUEUE = 2
|
||||
|
||||
function semaphore(integer n)
|
||||
if n>0 then
|
||||
sems = append(sems,{n,{}})
|
||||
return length(sems)
|
||||
else
|
||||
return 0
|
||||
end if
|
||||
end function
|
||||
|
||||
procedure acquire(integer id)
|
||||
if sems[id][COUNTER]=0 then
|
||||
task_suspend(task_self())
|
||||
sems[id][QUEUE] &= task_self()
|
||||
task_yield()
|
||||
end if
|
||||
sems[id][COUNTER] -= 1
|
||||
end procedure
|
||||
|
||||
procedure release(integer id)
|
||||
sems[id][COUNTER] += 1
|
||||
if length(sems[id][QUEUE])>0 then
|
||||
task_schedule(sems[id][QUEUE][1],1)
|
||||
sems[id][QUEUE] = sems[id][QUEUE][2..$]
|
||||
end if
|
||||
end procedure
|
||||
|
||||
function count(integer id)
|
||||
return sems[id][COUNTER]
|
||||
end function
|
||||
|
||||
procedure delay(atom delaytime)
|
||||
atom t = time()
|
||||
while time()-t<delaytime do
|
||||
task_yield()
|
||||
end while
|
||||
end procedure
|
||||
|
||||
integer sem = semaphore(4)
|
||||
|
||||
procedure worker()
|
||||
acquire(sem)
|
||||
printf(1,"- Task %d acquired semaphore.\n",task_self())
|
||||
delay(2)
|
||||
release(sem)
|
||||
printf(1,"+ Task %d released semaphore.\n",task_self())
|
||||
end procedure
|
||||
|
||||
for i=1 to 10 do
|
||||
integer task = task_create(routine_id("worker"),{})
|
||||
task_schedule(task,1)
|
||||
task_yield()
|
||||
end for
|
||||
|
||||
integer sc = 0
|
||||
atom t0 = time()+1
|
||||
while length(task_list())>1 do
|
||||
task_yield()
|
||||
integer scnew = count(sem)
|
||||
if scnew!=sc
|
||||
or time()>t0 then
|
||||
sc = scnew
|
||||
printf(1,"Semaphore count now %d\n",{sc})
|
||||
t0 = time()+2
|
||||
end if
|
||||
end while
|
||||
?"done"
|
||||
44
Task/Metered-concurrency/Ruby/metered-concurrency.rb
Normal file
44
Task/Metered-concurrency/Ruby/metered-concurrency.rb
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
require 'thread'
|
||||
|
||||
# Simple Semaphore implementation
|
||||
class Semaphore
|
||||
def initialize(size = 1)
|
||||
@queue = SizedQueue.new(size)
|
||||
size.times { acquire }
|
||||
end
|
||||
|
||||
def acquire
|
||||
tap { @queue.push(nil) }
|
||||
end
|
||||
|
||||
def release
|
||||
tap { @queue.pop }
|
||||
end
|
||||
|
||||
# @return [Integer]
|
||||
def count
|
||||
@queue.length
|
||||
end
|
||||
|
||||
def synchronize
|
||||
release
|
||||
yield
|
||||
ensure
|
||||
acquire
|
||||
end
|
||||
end
|
||||
|
||||
def foo(id, sem)
|
||||
sem.synchronize do
|
||||
puts "Thread #{id} Acquired lock"
|
||||
sleep(2)
|
||||
end
|
||||
end
|
||||
|
||||
threads = []
|
||||
n = 5
|
||||
s = Semaphore.new(3)
|
||||
n.times do |i|
|
||||
threads << Thread.new { foo i, s }
|
||||
end
|
||||
threads.each(&:join)
|
||||
8
Task/Metered-concurrency/Zkl/metered-concurrency.zkl
Normal file
8
Task/Metered-concurrency/Zkl/metered-concurrency.zkl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fcn job(name,sem){
|
||||
name.println(" wait"); sem.acquire();
|
||||
name.println(" go"); Atomic.sleep(2);
|
||||
sem.release(); name.println(" done")
|
||||
}
|
||||
// start 3 threads using the same semphore
|
||||
s:=Thread.Semaphore(1);
|
||||
job.launch("1",s); job.launch("2",s); job.launch("3",s);
|
||||
Loading…
Add table
Add a link
Reference in a new issue