Skip to content

Instantly share code, notes, and snippets.

@ejamesc
Created November 17, 2011 07:04
Show Gist options
  • Save ejamesc/1372562 to your computer and use it in GitHub Desktop.
Save ejamesc/1372562 to your computer and use it in GitHub Desktop.
Semaphore PS
"""
This simulation program works as follows:
The Task class contains a list of tasks to run, and tracks block state.
The Task.next() function exposes the next function of the generator tasks it contains.
When a block is called (via Task.block(name_of_task)) all other tasks except for
name_of_task will be added to the internal Task blocklist.
Task.next() will skip over any tasks currently on the blocklist
during Round-Robin iteration.
Task.release_block() clears the block list, thus allowing all other tasks to continue running
"""
class Semaphore():
"""Semaphore class, uses an empty list to keep track of resources
"""
def __init__(self):
self.items = []
self.MAX_AVAILABLE = 1 # can be whatever number of resources
self.available = self.MAX_AVAILABLE
def acquire(self, x, task):
self.items.append({x: task})
def release(self, x, task):
if [x, task] in items:
self.items.remove({x: task})
def is_acquired(self, x):
return True if x in self.items else False
class Task():
"""Task class, maintains block state
"""
def __init__(self):
self.gens = []
self.blocklist = []
def __init__(self, funclist):
self.gens = funclist
self.blocklist = []
def add(self, task):
self.gens.append(task)
def block(self, task):
self.blocklist = list(self.gens) # python clone list syntax
self.blocklist.remove(task)
def release_block(self):
self.blocklist = []
def next(self):
"""Round robin generator
"""
temp = self.gens[0]
self.gens.remove(temp)
self.gens.append(temp)
if temp in self.blocklist:
yield
else:
try:
yield temp.next()
except StopIteration:
# if task has ended, yield
yield
for x in self.next():
yield x
def task1(x):
reg = x[0]
print '1-1'
yield
reg = reg+1
print '1-2'
yield
sema.acquire(x[0])
x[0] = reg
#release(x[0])
print '1-3'
yield
def task2(x):
reg = x[0]
print '2-1'
yield
reg = reg+1
print '2-2'
yield
x[0] = reg
print '2-3'
yield
def scheduler():
x=[0]
taskfunc1 = task1(x)
taskfunc2 = task2(x)
tasker = Task([taskfunc1,taskfunc2])
for i in range(2):
next(tasker.next())
tasker.block(taskfunc1) #taskfunc1 is now blocking
for i in range(3):
next(tasker.next())
tasker.release_block() #other tasks apart from taskfunc1 may now run.
for i in range(3):
next(tasker.next())
print "x=", x[0]
# This is the main program, to demonstrate
sema = Semaphore()
scheduler()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment