Classic Reader Writer Problem

code

import random, simpy
INTERVAL = 3    #the maximum interval of adjacent two operations is 3
MAXTIME = 5     #the maximum execution time of a single operation is 5

datablocks = []        #the list of datablocks. Assume in this project there are 100 datablocks
processQueue = []    #the process waiting queue, set max size 4
req = []
for i in range(50):
    req.append(None)

class DataBlock(object):        #DataBlock object
    def __init__(self, lock, id, readersNum):
        self.lock = lock
        self.id = id
        self.readersNum = readersNum

class Operation(object):
    def __init__(self,env,capacity,maxtime):
        self.maxtime = maxtime
        self.env = env

    def read(self, env, name, datablock):
        global req
        datablock.readersNum = datablock.readersNum + 1
        if datablock.readersNum == 1:
            req[datablock.id] = datablock.lock.request()
            yield req[datablock.id]
        print("%s is reading datablock No.%s at %s" %(name,datablock.id,env.now))
        operateTime = random.randint(1,MAXTIME)
        yield env.timeout(operateTime)
        print("%s has finished reading datablock No.%s at %s" %(name,datablock.id,env.now))
        datablock.readersNum = datablock.readersNum -1
        if datablock.readersNum == 0:
            datablock.lock.release(req[datablock.id])
        processQueue.remove(name)

    def write(self, env, name, datablock):
        global req
        with datablock.lock.request() as r:
            yield r
            print("%s is writing datablock No.%s at %s" %(name,datablock.id,env.now))
            operateTime = random.randint(1,MAXTIME)
            yield env.timeout(operateTime)
            print("%s has finished writing datablock No.%s at %s" %(name,datablock.id,env.now))
            processQueue.remove(name)



def setup(env, capacity, maxtime, interval,datablocks):
    operation = Operation(env,capacity, maxtime)
    i = 0
    while  True:
        yield env.timeout(random.randint(0,interval))    #stop for next operation
        blockNum = random.randint(0,49)                    #generate block number randomly
        mode = "";
        if random.random()<0.25:                        #according possibility to specify the mode 
            mode = "W"
        else:
            mode = "R"

        if len(processQueue) == 4:                        #if the queue is full, wait
            yield env.timeout(maxtime*3)
        processQueue.append('Operation %d' %i)            #push current operate into the queue
        db = datablocks[blockNum]
        if mode == "R":
            env.process(operation.read(env,'Operation %d' % i,db))
        else:
            env.process(operation.write(env,'Operation %d' % i,db))
        i = i+1




#initialize datablock objects
env = simpy.Environment()
for i in range(50):
    datablocks.append(DataBlock(simpy.Resource(env, capacity=1),i,0)) 

env.process(setup(env, 5, MAXTIME, INTERVAL,datablocks))
env.run(until=1000)

results matching ""

    No results matching ""