Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- library PeriodicEvent /*
- */requires /*
- */Alloc /*
- */Timer /*
- */Table /*
- */Trigger /*
- */IntegerIndexer /*
- */BooleanExpression /*
- */Initializer /*
- *///! novjass
- |=========|
- | Credits |
- |=========|
- Author: AGD
- |-----|
- | API |
- |-----|
- struct Period/*
- */static constant integer TIMEOUT_PRECISION/*
- - The number of decimal digits that the system will consider to see if the timeouts are identical.
- - The default value is 5, you can change the value below (The recommended value is betweed 3 to 5).
- - A higher value supports higher timeout accuracy while a lower value results to higher timeout
- merge chance and results to a better increase in performance in tight executions so set the value
- at your own discretion.
- */readonly real timeout /* The periodic timeout
- */readonly real elapsed /* The elapsed time starting from the last expiration
- */readonly real remaining /* The remaining time before the next expiration
- */static method operator [] takes real timeout returns Period/*
- - Creates a new Period of a certain timeout
- */method destroy takes nothing returns nothing/*
- - Destroys a Period instance
- */method operator [] takes BoolExpr expr returns PeriodicEvent/*
- - Retreives the PeriodicEvent instance based on the BoolExpr parameter
- */method register takes BoolExpr expr returns PeriodicEvent/*
- - Creates a new PeriodicEvent instance based on the BoolExpr parameter
- */method unregister takes BoolExpr expr returns nothing/*
- - Unregisters the PeriodicEvent instance of the BoolExpr parameter from this Period
- */method registerTrigger takes Trigger t returns PeriodicEvent/*
- - Registers a Trigger to this Period instance
- */method unregisterTrigger takes Trigger t returns nothing/*
- - Unregisters a Trigger from this Period instance
- */struct PeriodicEvent/*
- */readonly Period period /* The Period in which this instance is registered
- */method addExecutionDuration takes real duration returns nothing/*
- - Adds an execution duration limit to a PeriodicEvent instance
- */method addExecutionLimit takes integer limit returns nothing/*
- - Adds an execution count limit to a PeriodicEvent instance
- */method resetExecutionHandler takes nothing returns nothing/*
- - Removes all execution limits for a PeriodicEvent instance
- *///! endnovjass
- /*===================================================================================*/
- private keyword EventCode
- struct Period extends array
- static constant integer TIMEOUT_PRECISION = 5
- readonly real timeout
- private Timer timer
- private Trigger trigger
- private integer count
- private boolean allocated
- private static integer multiplier
- implement IntegerIndexer
- method operator remaining takes nothing returns real
- return .timer.remaining
- endmethod
- method operator elapsed takes nothing returns real
- return .timer.elapsed
- endmethod
- private static method onExpire takes nothing returns nothing
- call Trigger(Timer.expired.data).evaluate()
- endmethod
- private method add takes BoolExpr expr returns PeriodicEvent
- local integer count = .count + 1
- set .count = count
- if count == 1 then
- call .timer.start(.timeout, true, function thistype.onExpire)
- endif
- if expr != 0 then
- return EventCode(this).insert(expr)
- endif
- return 0
- endmethod
- private method remove takes BoolExpr expr returns nothing
- local integer count = .count - 1
- set .count = count
- if count == 0 then
- call .timer.pause()
- endif
- if expr != 0 then
- call EventCode(this).remove(expr)
- endif
- endmethod
- static method operator [] takes real timeout returns thistype
- local integer timeoutInt = R2I(timeout*multiplier)
- local thistype this = getIntegerIndex(timeoutInt)
- if not .allocated then
- set .allocated = true
- set .trigger = Trigger.create()
- set .timer = Timer.newEx(.trigger)
- set .timeout = I2R(timeoutInt)/I2R(multiplier)
- endif
- return this
- endmethod
- method operator [] takes BoolExpr expr returns PeriodicEvent
- return EventCode.table[this][expr]
- endmethod
- method destroy takes nothing returns nothing
- if .allocated then
- set .allocated = false
- call removeIntegerIndex(getIntegerByIndex(this))
- call .trigger.destroy()
- call .timer.free()
- set .timeout = 0.00
- endif
- endmethod
- method register takes BoolExpr expr returns PeriodicEvent
- call .trigger.addCondition(expr)
- return .add(expr)
- endmethod
- method unregister takes BoolExpr expr returns nothing
- call .trigger.removeCondition(expr)
- call .remove(expr)
- endmethod
- method registerTrigger takes Trigger t returns PeriodicEvent
- call .trigger.hook(t)
- return .add(t.condition.expression)
- endmethod
- method unregisterTrigger takes Trigger t returns nothing
- call .trigger.unhook(t)
- call .remove(t.condition.expression)
- endmethod
- private static method init takes nothing returns nothing
- set multiplier = R2I(Pow(10, TIMEOUT_PRECISION))
- endmethod
- implement Initializer
- endstruct
- struct PeriodicEvent extends array
- private Timer eventTimer
- private BoolExpr expr
- method operator period takes nothing returns Period
- return EventCode(this).period
- endmethod
- private static method unregisterCode takes nothing returns nothing
- local Timer expired = Timer.expired
- local thistype this = expired.data
- call .period.unregister(thistype(expired).expr)
- call expired.free()
- set .eventTimer = 0
- set thistype(expired).expr = 0
- endmethod
- method addExecutionDuration takes real duration returns nothing
- local Period period = .period
- local real remaining = period.remaining
- if .eventTimer == 0 then
- set .eventTimer = Timer.newEx(this)
- endif
- if remaining == period.timeout then
- set remaining = 0.00
- endif
- call .eventTimer.start(remaining + duration, false, function thistype.unregisterCode)
- set thistype(.eventTimer).expr = EventCode(this).expr
- endmethod
- method addExecutionLimit takes integer limit returns nothing
- local Period period = .period
- local real remaining = period.remaining
- local real timeout = period.timeout
- if .eventTimer == 0 then
- set .eventTimer = Timer.newEx(this)
- endif
- if remaining == timeout then
- set remaining = 0.00
- endif
- call .eventTimer.start(remaining + timeout*limit, false, function thistype.unregisterCode)
- set thistype(.eventTimer).expr = EventCode(this).expr
- endmethod
- method resetExecutionHandler takes nothing returns nothing
- local Timer thisTimer = .eventTimer
- if thisTimer != 0 then
- call thisTimer.stop()
- call thisTimer.free()
- set .eventTimer = 0
- endif
- endmethod
- endstruct
- private struct EventCode extends array
- static TableArray table
- Period period
- integer expr
- implement Alloc
- method insert takes BoolExpr expr returns PeriodicEvent
- local thistype instance
- debug if table[this].has(expr) then
- debug call debug("|CFFFF0000ERROR: Attempt to double-register BoolExpr[" + I2S(expr) + "] to Period[" + I2S(this) + "]")
- debug return table[this][expr]
- debug endif
- set instance = allocate()
- set instance.period = this
- set instance.expr = expr
- set table[this][expr] = instance
- return instance
- endmethod
- method remove takes BoolExpr expr returns nothing
- local Table t = table[this]
- local thistype instance = t[expr]
- debug if not t.has(expr) then
- debug call debug("|CFFFF0000ERROR: Attempt to unregister an unregistered BoolExpr[" + I2S(expr) + "] from Period[" + I2S(this) + "]")
- debug return
- debug endif
- set instance.period = 0
- set instance.expr = 0
- call instance.deallocate()
- call t.remove(expr)
- endmethod
- private static method init takes nothing returns nothing
- set table = TableArray[0x2000]
- endmethod
- implement Initializer
- endstruct
- endlibrary
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement