Jump to content
Sign in to follow this  
jennico

Multithreading for AutoIt - finally

Recommended Posts

jennico

my _Adlib.au3 enables multiple instances of Adlib(). in this way you will be enabled to run random processes in one single script. in fact, there seem to be a universe of possible applications.

features:

nearly random instances possible (15999999 is the limit)

very accurate execution of threads

CPU gentle architecture by calculation of the highest suitable frequency

short and easy functions

random arguments can be passed to the Adlib functions

Adlib execution can be limited

and, as always in my scripts: no includes, no script breaking problems in the future.

_Adlib.au3 UDF

[autoit]#AutoIt3Wrapper_AU3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#cs

;#=#INDEX#===================================================#

;# Title .........: _Adlib.au3

;# Description ...: Enhanced Adlib functionality, enables multiple adlib instances, function parameters, limited adlibs, and adlib pausing

;# Date ..........: 6.11.08

;# Version .......: 1.0

;# Author ........: jennico (jennicoattminusonlinedotde)

;# Main Functions : _AdlibEnable ( "function" [, time [, count [, param]]] )

;# _AdlibDisable ( $al_ID = 0 )

;# _AdlibPause ( $al_ID = 0 )

;# _AdlibResume ( $al_ID = 0 )

;# _AdlibMainFreq ( )

;# _AdlibFreq ( $al_ID )

;# _AdlibFunc ( $al_ID )

;# _AdlibID ( $func )

;# _AdlibParams ( $al_ID )

;# _AdlibActive ( $al_ID = 0 )

;# Subfunctions ..: __AdlibAdd ( $al_ID [, $time] )

;# __AdlibMain ( )

;# __AdlibKill ( )

;# __Euclid ( $a, $b )

;#===========================================================#

#ce

#include-once

#Region;--------------------------Global declarations

__AdlibKill()

Global $al_timer = TimerInit()

#EndRegion;--------------------------Global declarations

#region;--------------------------Main Functions

#region;--------_AdlibEnable

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibEnable ( "function" [, time [, count [, param]]] )

;# Description....: Enables Multi Adlib functionality and starts a new adlib instance.

;# Parameters.....: function = The name of the adlib function to call.

;# time [optional] = frequency how often in milliseconds (> 0) to call the function. Default is 250 ms.

;# count [optional] = how many times (> 0) the function shall be call. Default is -1 (=continuous).

;# param [optional] = parameter or array of parameters passed to "function".

;# Return Value ..: Returns Adlib-ID to be used in the other functions

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: When using _AdlibEnable, the built-in AdlibEnable and AdlibDisable MUST not be used at the same time.

;# "function" has to be passed without parentheses.

;# When using count, the adlib instance will be stopped after count times and the Adlib_ID will be invalid.

;# To pass multiple parameters to function, pass a 1-based array. Element 0 is used internally and will be overwritten.

;# For an example on multiple arrays, refer to Function "Call" in help file.

;# A hint : If param is declared globally it can be updated dynamically.

;# To skip one parameter, use "-1".

;# Theoretical limit of Alib instances is 15,999,999.

;# Every 250 ms (or time ms) the specified "function" is called.

;# The adlib function should be kept simple as it is executed often and during this time the main script is paused.

;# Also, the time parameter should be used carefully to avoid CPU load.

;# If a previously registered function is passed, the adlib frequency will be updated and the corresponding already existing Adlib-ID will be returned.

;# Thus it is not possible to call the same function twice.

;# Important recommendation:

;# If possible, please use round (multiples of each others) time frequencies to avoid CPU load . The main calling frequency of multiple adlibs is their greatest common divisor.

;# E.g. for two adlib instances, better choose 100 and 50 (main=50) for time than 99 and 51 (main=3).

;# If you choose two primes instead, the main frequency will be 1 ms and your CPU will be locked.

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibDisable, _AdlibPause, _AdlibResume

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibEnable($func, $time = 250, $count = -1, $param = "")

If $time <= 0 Then $time = 250

If $count = 0 Then $count = -1

For $al_ID = 1 To $al_func[0]

If $al_func[$al_ID] = $func Then ExitLoop

Next

If $al_ID > $al_func[0] Then

ReDim $al_func[$al_ID + 1], $al_time[$al_ID + 1], $al_current[$al_ID + 1], _

$al_next[$al_ID + 1], $al_param[$al_ID + 1], $al_count[$al_ID + 1]

If IsArray($param) Then $param[0] = "CallArgArray"

$al_func[0] = $al_ID

$al_func[$al_ID] = $func

EndIf

$al_count[$al_ID] = $count

$al_param[$al_ID] = $param

$al_current[$al_ID] = $time

__AdlibAdd($al_ID, $time)

Return $al_ID

EndFunc ;==>_AdlibEnable

#EndRegion;--------_AdlibEnable

#region;--------_AdlibDisable

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibDisable ( $al_ID = 0 )

;# Description....: Stops specified adlib instance or disables entire adlib functionality.

;# Parameters.....: $al_ID [optional] = The Adlib-ID returned by a previous _AdlibEnable call.

;# If omitted or 0, all instances will be stopped and adlib functionality disabled.

;# Return Value ..: Success: Returns 1

;# Failure: Returns 0 if Adlib-ID is not valid (<0, not defined or stopped before).

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: NOT the same as AdlibDisable, do not use it when you use (Multi) _Adlib !

;# Instead of the Adlib-ID, the function name can be passed as an argument, if the name is not valid, 0 will be the return value.

;# When passing the Adlib-ID, make sure that it is a number !

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibPause, _AdlibResume

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibDisable($al_ID = 0);noch fehler in count !

If IsInt($al_ID) = 0 Then

$al_ID = _AdlibID($al_ID)

If $al_ID = 0 Then Return 0

EndIf

If $al_ID > $al_func[0] Or $al_ID < 0 Then Return 0

If $al_ID = 0 Then

__AdlibKill()

Return 1

EndIf

$al_next[$al_ID] = 0

$al_count[$al_ID] = 0

$al_current[$al_ID] = 0

$al_param[$al_ID] = ""

$al_func[$al_ID] = ""

__AdlibAdd($al_ID, 0)

Return 1

EndFunc ;==>_AdlibDisable

#EndRegion;--------_AdlibDisable

#region;--------_AdlibPause

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibPause ( $al_ID = 0 )

;# Description....: Pauses specified or all adlib instance(s).

;# Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.

;# Return Value ..: Success: Returns 1

;# Failure: Returns 0 if Adlib-ID is not valid (<0, not defined or stopped before).

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: If $al_ID omitted or 0, all instances will be paused.

;# Main frequency will not be updated on _AdlibPause.

;# Instead of the Adlib-ID, the function name can be passed as an argument.

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibResume, _AdlibActive

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibPause($al_ID)

If IsInt($al_ID) = 0 Then $al_ID = _AdlibID($al_ID)

If $al_ID > $al_func[0] Or $al_ID < 0 Then Return 0

If $al_ID = 0 Then

For $i = 1 To $al_func[0]

$al_current[$i] = 0

Next

Return 1

EndIf

$al_current[$al_ID] = 0

Return 1

EndFunc ;==>_AdlibPause

#EndRegion;--------_AdlibPause

#region;--------_AdlibResume

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibResume ( $al_ID = 0 )

;# Description....: Resumes specified or all (paused) adlib instance(s).

;# Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.

;# Return Value ..: Success: Returns 1

;# Failure: Returns 0 if Adlib-ID is not valid (<0, not defined or stopped before).

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: If $al_ID omitted or 0, all instances will be resumed.

;# Instead of the Adlib-ID, the function name can be passed as an argument.

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibResume($al_ID = 0)

If IsInt($al_ID) = 0 Then $al_ID = _AdlibID($al_ID)

If $al_ID > $al_func[0] Or $al_ID < 0 Then Return 0

If $al_ID = 0 Then

For $i = 1 To $al_func[0]

$al_current[$i] = $al_time[$i]

$al_next[$i] = TimerDiff($al_timer) + $al_time[$i] - _

Mod(TimerDiff($al_timer), $al_time[$i])

Next

Return 1

EndIf

$al_current[$al_ID] = $al_time[$al_ID]

$al_next[$al_ID] = TimerDiff($al_timer) + $al_time[$al_ID] - _

Mod(TimerDiff($al_timer), $al_time[$al_ID])

Return 1

EndFunc ;==>_AdlibResume

#EndRegion;--------_AdlibResume

#region;--------_AdlibMainFreq

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibMainFreq ( )

;# Description....: Returns the current main (overall) adlib frequency.

;# Parameters.....: none

;# Return Value ..: Success: the current main (overall) adlib frequency in ms. Minimum is 1.

;# Failure: Returns 0 if Multi adlib functionality is disabled.

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: Designed to observe and prevent CPU load. Highest possible load is on 1.

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibFreq, _AdlibFunc, _AdlibParams, _AdlibActive

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibMainFreq()

If $al_func[0] = 0 Then Return 0

Local $t

For $i = 1 To $al_func[0]

If $al_func[$i] Then

$t = $al_time[$i]

For $al_ID = $i + 1 To $al_func[0]

If $al_current[$al_ID] Then $t = __Euclid($t, $al_time[$al_ID])

Next

Return $t

EndIf

Next

__AdlibKill()

EndFunc ;==>_AdlibMainFreq

#EndRegion;--------_AdlibMainFreq

#region;--------_AdlibPause

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibFreq ( $al_ID )

;# Description....: Returns the specified adlib frequency.

;# Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.

;# Return Value ..: Success: Returns the specified adlib frequency in ms.

;# Failure: Returns 0 if Adlib-ID is not valid (0, not defined or stopped before).

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: Instead of the Adlib-ID, the function name can be passed as an argument.

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibMainFreq, _AdlibFunc, _AdlibID, _AdlibParams, _AdlibActive

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibFreq($al_ID)

If IsInt($al_ID) = 0 Then $al_ID = _AdlibID($al_ID)

If $al_ID > $al_func[0] Then Return 0

Return $al_time[$al_ID]

EndFunc ;==>_AdlibFreq

#EndRegion;--------_AdlibFreq

#region;--------_AdlibFunc

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibFunc ( $al_ID )

;# Description....: Returns the specified adlib function name.

;# Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.

;# Return Value ..: Success: Returns the specified adlib function name.

;# Failure: Returns "" (blank string) if Adlib-ID is not valid (not defined or stopped before).

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: If Sal_ID = 0 then the number of _Adlib instances (incl. stopped and paused) is returned.

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibMainFreq, _AdlibFreq, _AdlibID, _AdlibParams, _AdlibActive

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibFunc($al_ID)

If $al_ID > $al_func[0] Then Return ""

Return $al_func[$al_ID]

EndFunc ;==>_AdlibFunc

#EndRegion;--------_AdlibFunc

#region;--------_AdlibID

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibID ( $func )

;# Description....: Returns the Adlib-ID specified by passed function name.

;# Parameters.....: $func = The function name registered in a previous _AdlibEnable call.

;# Return Value ..: Success: Returns the Adlib-ID.

;# Failure: Returns 0 if specified function is not registered in previous _AdlibEnable call.

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: none

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibMainFreq, _AdlibFreq, _AdlibFunc, _AdlibParams, _AdlibActive

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibID($func)

For $al_ID = 1 To $al_func[0]

If $al_func[$al_ID] = $func Then Return $al_ID

Next

EndFunc ;==>_AdlibID

#EndRegion;--------_AdlibID

#region;--------_AdlibParams

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibParams ( $al_ID )

;# Description....: Returns an array of parameters and stats of the specified Adlib-ID.

;# Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.

;# Return Value ..: Success: Returns a 0 based 6 element array.

;# Failure: Returns "" (blank string) if Adlib-ID is not valid (not defined or = 0).

;# Author ........: jennico

;# Date ..........: 5.11.08

;# Remarks .......: The returned array contains:

;# Array[0] = (More or less) proper function name incl. parenthesis and parameters (if given and not an array).

;# Array[1] = current instance Status: 1 for active, 0 for stopped, 2 for paused.

;# Array[2] = the corresponding function name ("" (blank) if instance is stopped).

;# Array[3] = the corresponding frequency (0 if instance is stopped).

;# Array[4] = (> 0) amount of times the corresponding function has been called.

;# (< 0) If count was specified, element contains the count left.

;# (= 0) Instance has been stopped.

;# Array[5] = corresponding function parameters (can be an array itself) ("" (blank) if instance is stopped).

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibMainFreq, _AdlibFreq, _AdlibFunc, _AdlibID, _AdlibActive

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibParams($al_ID)

If $al_ID > $al_func[0] Or $al_ID = 0 Then Return ""

Local $ret[6]

$ret[1] = 1

If $al_func[$al_ID] = "" Then $ret[1] = 0

If $al_current[$al_ID] = 0 Then $ret[1] = 2

$ret[2] = $al_func[$al_ID]

$ret[3] = $al_time[$al_ID]

$ret[4] = $al_count[$al_ID] * - 1

If $ret[4] < 0 Then $ret[3] += 1

If $al_func[$al_ID] = "" Then $ret[4] = 0

$ret[5] = $al_param[$al_ID]

$ret[0] = $ret[2] & "(" & $ret[3] & "," & $ret[4] & "," & $ret[5] & ")"

Return $ret

EndFunc ;==>_AdlibParams

#EndRegion;--------_AdlibParams

#region;--------_AdlibActive

#cs

;#=#Function#================================================#

;# Name ..........: _AdlibActive ( $al_ID = 0 )

;# Description....: Checks if _Adlib instance is active / paused. Or: Retrieves all active _Adlib instances.

;# Parameters.....: $al_ID [optional] = The Adlib-ID returned by a previous _AdlibEnable call.

;# Return Value ..: Success: Returns 1 if instance is active, 0 if stopped, and 2 if paused.

;# If parameter omitted or = 0 : Returns a 0 based array containing all active _Adlib instances.

;# Failure: Returns -1 and sets @error to 1 if Adlib-ID is not valid.

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: If parameter omitted or = 0 :

;# Array[0] contains total numbers, elements 1 - Array[0] the active Adlib_IDs.

;# @extended contains the number of paused _Adlib instances. Paused instances are active, too.

;# Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibMainFreq, _AdlibFreq, _AdlibFunc, _AdlibParams, _AdlibParams

;# Example........: yes

;#===========================================================#

#ce

Func _AdlibActive($al_ID = 0)

If $al_ID > $al_func[0] Then Return SetError(1, 0, -1)

If $al_ID Then

Local $ret = 0

If $al_func[$al_ID] Then

$ret = 1

If $al_current[$al_ID] = 0 Then $ret = 2

EndIf

Return $ret

EndIf

Local $ret1 = "", $ret2 = 0

For $al_ID = 1 To $al_func[0]

If $al_func[$al_ID] Then

$ret1 &= $al_ID & "*"

If $al_current[$al_ID] = 0 Then $ret2 += 1

EndIf

Next

Return SetExtended($ret2, StringSplit(StringTrimRight($ret1, 1), "*"))

EndFunc ;==>_AdlibActive

#EndRegion;--------_AdlibActive

#EndRegion;--------------------------Main Functions

#Region;--------------------------Internal Functions

#cs

;#=#Function#================================================#

;# Name ..........: __AdlibAdd ( $al_ID [, $time] )

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: internal use only

;# Example........: no

;#===========================================================#

#ce

Func __AdlibAdd($al_ID, $time)

$al_time[$al_ID] = $time

Local $t = _AdlibMainFreq()

If $t = 0 Then Return

If $time Then $al_next[$al_ID] = TimerDiff($al_timer) + $time

AdlibEnable("__AdlibMain", $t)

EndFunc ;==>__AdlibAdd

#cs

;#=#Function#================================================#

;# Name ..........: __AdlibMain ( )

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: internal use only

;# Example........: no

;#===========================================================#

#ce

Func __AdlibMain()

For $al_ID = 1 To $al_func[0]

If $al_current[$al_ID] And TimerDiff($al_timer) >= $al_next[$al_ID] Then

If $al_param[$al_ID] Then

Call($al_func[$al_ID], $al_param[$al_ID])

Else

Call($al_func[$al_ID])

EndIf

$al_count[$al_ID] -= 1

$al_next[$al_ID] += $al_time[$al_ID]

If $al_count[$al_ID] = 0 Then _AdlibDisable($al_ID)

EndIf

Next

EndFunc ;==>__AdlibMain

#cs

;#=#Function#================================================#

;# Name ..........: __AdlibKill ( )

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: internal use only

;# Example........: no

;#===========================================================#

#ce

Func __AdlibKill()

Global $al_func[1] = [0], $al_time[1] = [0], $al_current[1] = [0], _

$al_next[1] = [0], $al_param[1] = [0], $al_count[1] = [0]

EndFunc ;==>__AdlibKill

#cs

;#=#Function#================================================#

;# Name ..........: __Euclid ( $a, $b )

;# Description....: Calculates the Greatest Common Divisor

;# Parameters.....: $a = 1st Integer

;# $b = 2nd Integer

;# Return Value ..: Returns GCD

;# Author ........: jennico

;# Date ..........: 4.11.08

;# Remarks .......: internal use only

;# taken from _Primes.au3

;# Example........: no

;#===========================================================#

#ce

Func __Euclid($a, $B)

If $b = 0 Then Return $a

Return __Euclid($b, Mod($a, $B))

EndFunc ;==>__Euclid

#EndRegion;--------------------------Internal Functions


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
jennico

and i forgot some important features:

pausing and resuming of instances

dynamical updating of parameters to Adlib functions

v1.1

i add a new version here, because cannot edit first post anymore.

some slight improvements, additional param in _AdlibPause.

v1.2

lots of changes, improvements towards synchronicity of the threads

new functions : _AdlibUpdate, _AdlibSync

_Adlib.au3 UDF v1.2:

#AutoIt3Wrapper_AU3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#cs
    ;#=#INDEX#===================================================#
    ;#  Title .........: _Adlib.au3
    ;#  Description ...: Enhanced Adlib functionality, enables multiple adlib instances, function parameters, limited adlibs, and adlib pausing
    ;#  Date ..........: 8.11.08
    ;#  Version .......: 1.2 improved AdlibDisable, _AdlibResume, _AdlibAdd and __AdlibMain
    ;#                       _AdlibDisable will not break the "rythm" anymore
    ;#                       added _AdlibUpdate
    ;#                       added _AdlibSync
    ;#                       added _Sync parameter to _AdlibEnable
    ;#                       fixed bug when last instance disabled by count
    ;#                       fixed bug in _AdlibResume (resuming disabled)
    ;#                       generally improved synchronicity of instances
    ;#                       changed: one function can be called by different instances now.
    ;#  History .......: v1.1   7.11.08
    ;#                          some descriptions precizised
    ;#                          added forgotten AdlibDisable() in __AdlibKill
    ;#                          added count param to _AdlibPause
    ;#                   v1.0   6.11.08
    ;#  Author ........: jennico (jennicoattminusonlinedotde)
    ;#  Main Functions : _AdlibEnable ( "function" [, time [, count [, param]]] )
    ;#                   _AdlibDisable ( [$al_ID] )
    ;#                   _AdlibPause ( [$al_ID [, $count]] )
    ;#                   _AdlibResume ( [$al_ID] )
    ;#                   _AdlibUpdate ( $al_ID, time [, count [, param]] )
    ;#                   _AdlibSync ( $al_ID1, $al_ID2 )
    ;#                   _AdlibMainFreq ( )
    ;#                   _AdlibFreq ( $al_ID )
    ;#                   _AdlibFunc ( $al_ID )
    ;#                   _AdlibID ( $func )
    ;#                   _AdlibParams ( $al_ID )
    ;#                   _AdlibActive ( [$al_ID] )
    ;#  Subfunctions ..: __AdlibAdd ( $al_ID [, $time] )
    ;#                   __AdlibMain ( )
    ;#                   __AdlibKill ( )
    ;#                   __Euclid ( $a, $b )
    ;#===========================================================#
#ce

#include-once

#Region;--------------------------Global declarations

__AdlibKill()
Global $al_timer = TimerInit()

#EndRegion;--------------------------Global declarations
#region;--------------------------Main Functions
#region;--------_AdlibEnable

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibEnable ( "function" [, time [, count [, param [, sync ]]]] )
    ;#  Description....: Enables Multi Adlib functionality and starts a new adlib instance.
    ;#  Parameters.....: function = The name of the adlib function to call (without parentheses).
    ;#                   time [optional] = frequency how often in milliseconds (> 0) to call the function. Default is 250 ms.
    ;#                   count [optional] = how many times (> 0) the function shall be called ("time ticks"). Default is -1 (=continuous).
    ;#                   param [optional] = parameter or array of parameters to be passed to "function".
    ;#                   sync [optional] = Adlib-ID returned by a previously enabled instance.
    ;#  Return Value ..: Returns Adlib-ID to be used in the other functions.
    ;#                   Returns 0 if sync is not valid.
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: When using _AdlibEnable, the built-in AdlibEnable and AdlibDisable MUST not be used at all at the same time. This would deactivate all instances immediately.
    ;#                   When using count, the adlib instance will be disabled after count ticks of time and the Adlib-ID will be invalid.
    ;#                   When using sync, the start of the instance will be synchronized with the next tick of the instance represented by the specified Adlib-ID (results in a delay).
    ;#                   To pass multiple parameters to function, pass a 1-based array. Element 0 is used internally and will be overwritten.
    ;#                   For an example on multiple params, refer to Function "Call" in help file.
    ;#                   To skip one parameter, use "" (blank string).
    ;#                   A hint : If param (function parameter) is declared globally it can be updated dynamically without using any of these functions.
    ;#                   Theoretical limit of Alib instances is 15,999,999.
    ;#                   Every 250 ms (or time ms) the specified "function" is called.
    ;#                   The adlib function should be kept simple as it is executed often and during this time the main script is paused.
    ;#                   Also, the time parameter should be used carefully to avoid CPU load.
    ;#                   To update a parameter, use _AdlibUpdate.
    ;#                   NEW : Two or more instances can call the same function now. So you can use one adlib function to be called from several instances with different parameters.
    ;#                   Important recommendation:
    ;#                   If possible, please use round (multiples of each others) time frequencies to avoid CPU load . The main calling frequency of multiple adlibs is their greatest common divisor.
    ;#                   E.g. for two adlib instances, better choose 100 and 50 (main=50) for time than 99 and 51 (main=3).
    ;#                   If you choose two primes instead, the main frequency will be 1 ms and your CPU will possibly be locked.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibEnable($func, $time = 250, $count = -1, $param = "", $sync = 0)
    If $sync < 0 Or $sync > $al_func[0] Or $al_func[$sync] = "" And $sync <> 0 Then Return
    If $time <= 0 Then $time = 250
    If $count = 0 Then $count = -1
    $al_ID = $al_func[0] + 1
    ReDim $al_func[$al_ID + 1], $al_time[$al_ID + 1], $al_current[$al_ID + 1], _
            $al_next[$al_ID + 1], $al_param[$al_ID + 1], $al_count[$al_ID + 1]
    If IsArray($param) Then $param[0] = "CallArgArray" 
    $al_func[0] = $al_ID
    $al_func[$al_ID] = $func
    $al_count[$al_ID] = $count
    $al_param[$al_ID] = $param
    $al_current[$al_ID] = $time
    If $sync = 0 Then
        __AdlibAdd($al_ID, $time)
    Else
        $al_next[$al_ID] = $al_next[$sync]
        $al_update = 1
    EndIf
    Return $al_ID
EndFunc   ;==>_AdlibEnable

#EndRegion;--------_AdlibEnable
#region;--------_AdlibDisable

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibDisable ( [$al_ID] )
    ;#  Description....: Stops specified adlib instance or disables entire adlib functionality.
    ;#  Parameters.....: $al_ID [optional] = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#                   If omitted or 0, all instances will be stopped and adlib functionality disabled.
    ;#  Return Value ..: Success: Returns 1
    ;#                   Special: Returns 2 if all processes killed (Success)
    ;#                   Failure: Returns 0 if Adlib-ID is not valid (<0, not defined or disabled before).
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: NOT the same as AdlibDisable, do not use it when you use (Multi) _Adlib !
    ;#                   Instead of the Adlib-ID, the function name can be passed as an argument, if the name is not valid, 0 will be the return value. Be careful when the function is used by more than one instance.
    ;#                   When passing the Adlib-ID, make sure that it is a number !
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibDisable($al_ID = 0)
    If IsInt($al_ID) = 0 Then
        $al_ID = _AdlibID($al_ID)
        If $al_ID = 0 Then Return 0
    EndIf
    If $al_ID > $al_func[0] Or $al_ID < 0 Then Return 0
    If $al_ID = 0 Then
        __AdlibKill()
        Return 1
    EndIf
    $al_next[$al_ID] = 0
    $al_count[$al_ID] = 0
    $al_current[$al_ID] = 0
    $al_param[$al_ID] = ""
    $al_func[$al_ID] = ""
    $al_update = 1
    If __AdlibAdd($al_ID, 0) = 0 Then Return 2
    Return 1
EndFunc   ;==>_AdlibDisable

#EndRegion;--------_AdlibDisable
#region;--------_AdlibPause

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibPause ( [$al_ID [, $count]] )
    ;#  Description....: Pauses specified or all adlib instance(s).
    ;#  Parameters.....: $al_ID [optional] = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#                   $count [optional] = how many times (> 0) the function shall be paused ("time ticks").
    ;#  Return Value ..: Success: Returns 1
    ;#                   Failure: Returns 0 if Adlib-ID is not valid (<0, not defined or disabled before).
    ;#  Author ........: jennico
    ;#  Date ..........: 7.11.08
    ;#  Remarks .......: If $al_ID omitted or 0, all instances will be paused.
    ;#                   Setting count, the function will be automatically resumed after the specified ticks of time. If you have enabled the function with count parameter before, it will not be automatically disabled anmymore (previous count gets lost).
    ;#                   Main frequency will not be updated on _AdlibPause.
    ;#                   Instead of the Adlib-ID, the function name can be passed as an argument. Be careful when the function is used by more than one instance.
    ;#                   _AdlibPause will preserve the call "rythm", while _AdlibDisable followed by _AdlibEnable starts a new rythm.
    ;#                   On the other hand, if you want to resume immediately, use _AdlibEnable.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibResume, _AdlibActive, _AdlibUpdate, _AdlibSync
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibPause($al_ID = 0, $count = -1)
    If IsInt($al_ID) = 0 Then $al_ID = _AdlibID($al_ID)
    If $al_ID > $al_func[0] Or $al_ID < 0 Then Return 0
    If $al_ID = 0 Then
        Local $t = 0
        For $i = 1 To $al_func[0]
            If $al_func[$i] Then
                $al_current[$i] = 0
                $al_count[$i] = $count
                $t = 1
            EndIf
        Next
        Return $t
    EndIf
    If $al_func[$al_ID] = "" Then Return
    $al_current[$al_ID] = 0
    $al_count[$al_ID] = $count
    Return 1
EndFunc   ;==>_AdlibPause

#EndRegion;--------_AdlibPause
#region;--------_AdlibResume

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibResume ( [$al_ID] )
    ;#  Description....: Resumes specified or all (paused) adlib instance(s).
    ;#  Parameters.....: $al_ID [optional] = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#  Return Value ..: Success: Returns 1
    ;#                   Failure: Returns 0 if Adlib-ID is not valid (<0, not defined or disabled before).
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: If $al_ID omitted or 0, all instances will be resumed.
    ;#                   Instead of the Adlib-ID, the function name can be passed as an argument. Be careful when the function is used by more than one instance.
    ;#                   The difference to _AdlibEnable is that the function will be resumed to the same rythm as before, while _AdlibEnable starts a new rythm.
    ;#                   On the other hand, if you want to resume immediately, use _AdlibEnable.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibUpdate, _AdlibSync
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibResume($al_ID = 0)
    If IsInt($al_ID) = 0 Then $al_ID = _AdlibID($al_ID)
    If $al_ID > $al_func[0] Or $al_ID < 0 Then Return 0
    If $al_ID = 0 Then
        Local $t = 0
        For $i = 1 To $al_func[0]
            If $al_func[$i] Then
                $al_current[$i] = $al_time[$i]
                $t = 1
            EndIf
        Next
        Return $t
    EndIf
    If $al_func[$al_ID] = "" Then Return
    $al_current[$al_ID] = $al_time[$al_ID]
    Return 1
EndFunc   ;==>_AdlibResume

#EndRegion;--------_AdlibResume
#region;--------_AdlibUpdate

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibUpdate ( $al_ID, time [, count [, param]] )
    ;#  Description....: Updates parameters of specified adlib instance(s).
    ;#  Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#                   time [optional] = new frequency in ms.
    ;#                   count [optional] = new new count in ticks.
    ;#                   param [optional] = new params to be passed to specified function.
    ;#  Return Value ..: Success: Returns 1
    ;#                   Failure: Returns 0 if Adlib-ID is not valid (<0, not defined or disabled before).
    ;#  Author ........: jennico
    ;#  Date ..........: 8.11.08
    ;#  Remarks .......: If $al_ID = 0, all instances will be updated.
    ;#                   To omit time or count, use "0" or "" (blank string)
    ;#                   Instead of the Adlib-ID, the function name can be passed as an argument. Be careful when the function is used by more than one instance.
    ;#                   The difference to _AdlibEnable is that the function will keep up its rythm, while _AdlibEnable starts a new rythm.
    ;#                   With _AdlibUpdate it is possible to change function params, even if they are not declared globally.
    ;#                   Paused instances will be resumed.
    ;#                   Please observe: the updating of a frequency will not be realized instantly, but right after the next call of ANY (not necessarily the specified) adlib function !
    ;#                   This is necessary in order to preserve the current rythm.
    ;#                   Thus you will possibly notice a delay on first new tick.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibSync
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibUpdate($al_ID, $time = 0, $count = 0, $param = "")
    If IsInt($al_ID) = 0 Then $al_ID = _AdlibID($al_ID)
    If $al_ID > $al_func[0] Or $al_ID < 0 Then Return 0
    If $al_ID = 0 Then
        Local $t = 0
        For $al_ID = 1 To $al_func[0]
            If $al_func[$al_ID] Then
                If IsArray($param) Then $param[0] = "CallArgArray" 
                If $time > 0 Then
                    $al_current[$al_ID] = $time
                    $al_time[$al_ID] = $time
                EndIf
                If $count > 0 Then $al_count[$al_ID] = $count
                If $param Then $al_param[$al_ID] = $param
                $t = 1
            EndIf
        Next
        If $t = 0 Then Return
        If $time > 0 Then $al_update = $time
        Return 1
    EndIf
    If $al_func[$al_ID] = "" Then Return
    If IsArray($param) Then $param[0] = "CallArgArray" 
    If $time > 0 Then
        $al_current[$al_ID] = $time
        $al_time[$al_ID] = $time
        $al_update = 1
    EndIf
    If $count > 0 Then $al_count[$al_ID] = $count
    If $param Then $al_param[$al_ID] = $param
    Return 1
EndFunc   ;==>_AdlibUpdate

#EndRegion;--------_AdlibUpdate
#region;--------_AdlibSync

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibSync ( $al_ID1, $al_ID2 )
    ;#  Description....: Synchronizes two (or more) _Adlib instances.
    ;#  Parameters.....: $al_ID1 = The instance to be synchronized.
    ;#                   $al_ID1 = The instance to be synchronized with.
    ;#  Return Value ..: Success: Returns 1
    ;#                   Failure: Returns 0 if one of the Adlib-IDs is not valid (<0, not defined or disabled before).
    ;#  Author ........: jennico
    ;#  Date ..........: 8.11.08
    ;#  Remarks .......: If $al_ID1 = 0, all instances will be synchronized with $al_ID2.
    ;#                   Synchronizing means restarting two or more instances ($al_ID1) right at the next call event of $al_ID2 without breaking the rythm of $al_ID2.
    ;#                   Very useful e.g. for collision implementations.
    ;#                   Instead of the Adlib-IDs, the function names can be passed as arguments. Be careful when the function is used by more than one instance.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibSync($al_ID1, $al_ID2)
    If IsInt($al_ID1) = 0 Then $al_ID1 = _AdlibID($al_ID1)
    If IsInt($al_ID2) = 0 Then $al_ID2 = _AdlibID($al_ID2)
    If $al_ID1 > $al_func[0] Or $al_ID1 < 0 Or $al_ID2 > $al_func[0] _
            Or $al_ID2 < 0 Or $al_func[$al_ID2] = "" Then Return 0
    If $al_ID1 = 0 Then
        Local $t = 0
        For $al_ID = 1 To $al_func[0]
            If $al_func[$al_ID] And $al_ID <> $al_ID2 Then
                $al_next[$al_ID] = $al_next[$al_ID2]
                $t = 1
            EndIf
        Next
        Return $t
    EndIf
    If $al_func[$al_ID1] = "" Then Return
    $al_next[$al_ID1] = $al_next[$al_ID2]
    Return 1
EndFunc   ;==>_AdlibSync

#EndRegion;--------_AdlibSync
#region;--------_AdlibMainFreq

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibMainFreq ( )
    ;#  Description....: Returns the current main (overall) adlib frequency.
    ;#  Parameters.....: none [ $p only used internally ]
    ;#  Return Value ..: Success: the current main (overall) adlib frequency in ms. Minimum is 1.
    ;#                   Failure: Returns 0 if Multi adlib functionality is disabled.
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: Designed to observe and prevent CPU load. Highest possible load is on 1.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync, _AdlibFreq, _AdlibFunc, _AdlibParams, _AdlibActive
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibMainFreq($p = 1)
    If $al_func[0] = 0 Then Return 0
    Local $t
    For $i = 1 To $al_func[0]
        If $al_func[$i] Then
            $t = $al_time[$i]
            For $al_ID = $i + 1 To $al_func[0]
                If $al_current[$al_ID] Then $t = __Euclid($t, $al_time[$al_ID])
            Next
            Return $t
        EndIf
    Next
    If $p = 1 Then __AdlibKill()
EndFunc   ;==>_AdlibMainFreq

#EndRegion;--------_AdlibMainFreq
#region;--------_AdlibFreq

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibFreq ( $al_ID )
    ;#  Description....: Returns the specified adlib frequency.
    ;#  Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#  Return Value ..: Success: Returns the specified adlib frequency in ms.
    ;#                   Failure: Returns 0 if Adlib-ID is not valid (0, not defined or disabled before).
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: Instead of the Adlib-ID, the function name can be passed as an argument. Be careful when the function is used by more than one instance.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync, _AdlibMainFreq, _AdlibFunc, _AdlibID, _AdlibParams, _AdlibActive
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibFreq($al_ID)
    If IsInt($al_ID) = 0 Then $al_ID = _AdlibID($al_ID)
    If $al_ID > $al_func[0] Then Return 0
    Return $al_time[$al_ID]
EndFunc   ;==>_AdlibFreq

#EndRegion;--------_AdlibFreq
#region;--------_AdlibFunc

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibFunc ( $al_ID )
    ;#  Description....: Returns the specified adlib function name.
    ;#  Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#  Return Value ..: Success: Returns the specified adlib function name.
    ;#                   Failure: Returns "" (blank string) if Adlib-ID is not valid (not defined or disabled before).
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: If Sal_ID = 0 then the number of _Adlib instances (incl. disabled and paused) is returned.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync, _AdlibMainFreq, _AdlibFreq, _AdlibID, _AdlibParams, _AdlibActive
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibFunc($al_ID)
    If $al_ID > $al_func[0] Then Return ""
    Return $al_func[$al_ID]
EndFunc   ;==>_AdlibFunc

#EndRegion;--------_AdlibFunc
#region;--------_AdlibID

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibID ( $func )
    ;#  Description....: Returns the Adlib-ID specified by passed function name.
    ;#  Parameters.....: $func = The function name registered in a previous _AdlibEnable call.
    ;#  Return Value ..: Success: Returns the Adlib-ID.
    ;#                   Failure: Returns 0 if specified function is not registered in previous _AdlibEnable call.
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: none
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync, _AdlibMainFreq, _AdlibFreq, _AdlibFunc, _AdlibParams, _AdlibActive
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibID($func)
    For $al_ID = 1 To $al_func[0]
        If $al_func[$al_ID] = $func Then Return $al_ID
    Next
EndFunc   ;==>_AdlibID

#EndRegion;--------_AdlibID
#region;--------_AdlibParams

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibParams ( $al_ID )
    ;#  Description....: Returns an array of parameters and stats of the specified Adlib-ID.
    ;#  Parameters.....: $al_ID = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#  Return Value ..: Success: Returns a 0 based 6 element array.
    ;#                   Failure: Returns "" (blank string) if Adlib-ID is not valid (not defined or = 0).
    ;#  Author ........: jennico
    ;#  Date ..........: 5.11.08
    ;#  Remarks .......: The returned array contains:
    ;#                   Array[0] = (More or less) proper function name incl. parenthesis and parameters (if given and not an array).
    ;#                   Array[1] = current instance Status: 1 for active, 0 for disabled, 2 for paused.
    ;#                   Array[2] = the corresponding function name ("" (blank) if instance is disabled).
    ;#                   Array[3] = the corresponding frequency (0 if instance is disabled).
    ;#                   Array[4] = (> 0) amount of times the corresponding function has been called.
    ;#                              (< 0) If count was specified, element contains the remainig count (time ticks).
    ;#                              (= 0) Instance has been stopped.
    ;#                   Array[5] = corresponding function parameters (can be an array itself) ("" (blank) if instance is disabled).
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync, _AdlibMainFreq, _AdlibFreq, _AdlibFunc, _AdlibID, _AdlibActive
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibParams($al_ID)
    If $al_ID > $al_func[0] Or $al_ID = 0 Then Return ""
    Local $ret[6]
    $ret[1] = 1
    If $al_func[$al_ID] = "" Then $ret[1] = 0
    If $al_current[$al_ID] = 0 Then $ret[1] = 2
    $ret[2] = $al_func[$al_ID]
    $ret[3] = $al_time[$al_ID]
    $ret[4] = $al_count[$al_ID] * - 1
    If $ret[4] < 0 Then $ret[3] += 1
    If $al_func[$al_ID] = "" Then $ret[4] = 0
    $ret[5] = $al_param[$al_ID]
    $ret[0] = $ret[2] & "(" & $ret[3] & "," & $ret[4] & "," & $ret[5] & ")" 
    Return $ret
EndFunc   ;==>_AdlibParams

#EndRegion;--------_AdlibParams
#region;--------_AdlibActive

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: _AdlibActive ( [$al_ID] )
    ;#  Description....: Checks if _Adlib instance is active / paused. Or: Retrieves all active _Adlib instances.
    ;#  Parameters.....: $al_ID [optional] = The Adlib-ID returned by a previous _AdlibEnable call.
    ;#  Return Value ..: Success: Returns 1 if instance is active, 0 if disabled, and 2 if paused.
    ;#                            If parameter omitted or = 0 : Returns a 0 based array containing all active _Adlib instances.
    ;#                   Failure: Returns -1 and sets @error to 1 if Adlib-ID is not valid.
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: If parameter omitted or = 0 :
    ;#                   Array[0] contains total numbers, elements 1 - Array[0] the active Adlib_IDs.
    ;#                   @extended contains the number of paused _Adlib instances. Paused instances are active, too.
    ;#  Related........: AdlibEnable, AdlibDisable, Call, _AdlibEnable, _AdlibDisable, _AdlibPause, _AdlibResume, _AdlibUpdate, _AdlibSync, _AdlibMainFreq, _AdlibFreq, _AdlibFunc, _AdlibParams, _AdlibParams
    ;#  Example........: yes
    ;#===========================================================#
#ce

Func _AdlibActive($al_ID = 0)
    If $al_ID > $al_func[0] Then Return SetError(1, 0, -1)
    If $al_ID Then
        Local $ret = 0
        If $al_func[$al_ID] Then
            $ret = 1
            If $al_current[$al_ID] = 0 Then $ret = 2
        EndIf
        Return $ret
    EndIf
    Local $ret1 = "", $ret2 = 0
    For $al_ID = 1 To $al_func[0]
        If $al_func[$al_ID] Then
            $ret1 &= $al_ID & "*" 
            If $al_current[$al_ID] = 0 Then $ret2 += 1
        EndIf
    Next
    Return SetExtended($ret2, StringSplit(StringTrimRight($ret1, 1), "*"))
EndFunc   ;==>_AdlibActive

#EndRegion;--------_AdlibActive
#EndRegion;--------------------------Main Functions
#Region;--------------------------Internal Functions
#cs
    ;#=#Function#================================================#
    ;#  Name ..........: __AdlibAdd ( $al_ID, $time )
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: internal use only
    ;#  Example........: no
    ;#===========================================================#
#ce

Func __AdlibAdd($al_ID, $time)
    $al_time[$al_ID] = $time
    Local $t = _AdlibMainFreq($time)
    If $time = 0 Then Return $t
    $al_next[$al_ID] = TimerDiff($al_timer) + $time
    AdlibEnable("__AdlibMain", _AdlibMainFreq())
EndFunc   ;==>__AdlibAdd

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: __AdlibMain ( )
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: internal use only
    ;#  Example........: no
    ;#===========================================================#
#ce

Func __AdlibMain()
    If $al_update Then
        AdlibEnable("__AdlibMain", _AdlibMainFreq())
        $al_update = 0
    EndIf
    Local $t = TimerDiff($al_timer)
    For $al_ID = 1 To $al_func[0]
        If $t >= $al_next[$al_ID] And $al_func[$al_ID] Then
            If $al_current[$al_ID] Then
                If $al_param[$al_ID] Then
                    Call($al_func[$al_ID], $al_param[$al_ID])
                Else
                    Call($al_func[$al_ID])
                EndIf
                $al_count[$al_ID] -= 1
                If $al_count[$al_ID] = 0 Then _AdlibDisable($al_ID)
            ElseIf $al_count[$al_ID] > 0 Then
                $al_count[$al_ID] -= 1
                If $al_count[$al_ID] = 0 Then _AdlibResume($al_ID)
            EndIf
            $al_next[$al_ID] += $al_time[$al_ID]
        EndIf
    Next
EndFunc   ;==>__AdlibMain

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: __AdlibKill ( )
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: internal use only
    ;#  Example........: no
    ;#===========================================================#
#ce

Func __AdlibKill()
    AdlibDisable()
    Global $al_func[1] = [0], $al_time[1] = [0], $al_current[1] = [0], _
            $al_next[1] = [0], $al_param[1] = [0], $al_count[1] = [0], $al_update = 0
EndFunc   ;==>__AdlibKill

#cs
    ;#=#Function#================================================#
    ;#  Name ..........: __Euclid ( $a, $b )
    ;#  Description....: Calculates the Greatest Common Divisor
    ;#  Parameters.....: $a = 1st Integer
    ;#                   $b = 2nd Integer
    ;#  Return Value ..: Returns GCD
    ;#  Author ........: jennico
    ;#  Date ..........: 4.11.08
    ;#  Remarks .......: internal use only
    ;#                   taken from _Primes.au3
    ;#  Example........: no
    ;#===========================================================#
#ce

Func __Euclid($a, $b)
    If $b = 0 Then Return $a
    Return __Euclid($b, Mod($a, $b))
EndFunc   ;==>__Euclid

#EndRegion;--------------------------Internal Functions

j.

Edited by jennico

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
Skrip

Wow. Very nice actually! This is the closest thing to multithreading I have seen. Great job.


[left][sub]We're trapped in the belly of this horrible machine.[/sub][sup]And the machine is bleeding to death...[/sup][sup][/sup][/left]

Share this post


Link to post
Share on other sites
jennico

thank you !! :mellow:

please more comments. i am not sure about some details in the functions. the params and count is not tested thoroughly. so please tell me your testing results that i can fix problems.

j.


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
spudw2k

Pretty cool. Reminds me of the adlib manager that ResNullius made, but more dynamic. I did some timing testing and it looks good so far. :mellow: Very nice.

Share this post


Link to post
Share on other sites
BillLuvsU

Looks very nice, havn't had a chance to play with it yet but I will try to get around to it.


[center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw

Share this post


Link to post
Share on other sites
jennico

i was thinking all the time to find a good example script demonstrating the abilities of my _adlib instances and using the dynamical parameter updating .....

so, just imagine to implement a billard game - nine ball. (oh i have been thinking of this since my last school days !) in a script without mulithreading you would update the rolling balls every nth discrete step. some of the balls are faster than the others, so they will have to "jump" to the next step. the result will not be very satisfying. the movements will be unrealistic and the fast balls will rather jump than roll.

but now you could use my adlib instances, one for each ball, and let them roll according to their speed. the faster balls will have a higher frequency of function calls than the slower ones and the game will be much more realistic since you won't see any "jumps" anymore.

everytime a ball collides with another one or hits the table rim you will have to update the parameters (speed, direction, spin) and when you have declared them globally, they will be updated dynamically and automatically passed to the ball functions that calculate the new position.

in this way you can leave the nine adlib functions work alone calculating and moving "their" ball positions in individual frequencies without having to change them every part of a second and without doing the calculation in one big main loop for all balls. the main loop will only have the job of observing and precalculating the collisions. this is a good model of what multithreading is good for.

i think this could be a fascinating implementation and maybe it's worth a try... .........

j.

Edited by jennico

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
jennico

thanks, guys !

@ spudw2k : i paid special attention to the correct and accurate timing. i am quite sure that this turned out fine. the secret clue is the greatest common divisor thing. !!

j.

Edited by jennico

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
WeMartiansAreFriendly

Very nice job! :mellow:

Here's a pretty neat example, what impresses me most is the 0% CPU usage and It's quite fast, and doesn't freeze up the whole script (unless you use a loop)

CODE

#include <ButtonConstants.au3>

#include <EditConstants.au3>

#include <GUIConstantsEx.au3>

#include <ListBoxConstants.au3>

#include <ProgressConstants.au3>

#include <SliderConstants.au3>

#include <StaticConstants.au3>

#include <WindowsConstants.au3>

#include <GuiComboBox.au3>

#Include <GuiListBox.au3>

#Include <GuiEdit.au3>

#Include "_Adlib.au3"

#Region ### START Koda GUI section ### Form=

$Form1 = GUICreate("Form1", 427, 407, 193, 125)

$List1 = GUICtrlCreateList("", 8, 8, 201, 214)

$List2 = GUICtrlCreateList("", 216, 8, 193, 214)

$Progress1 = GUICtrlCreateProgress(8, 232, 150, 17)

$Slider1 = GUICtrlCreateSlider(8, 256, 150, 45)

$Button1 = GUICtrlCreateButton("Button1", 8, 312, 75, 25, 0)

$Button2 = GUICtrlCreateButton("Button2", 8, 352, 75, 25, 0)

$Edit1 = GUICtrlCreateEdit("", 216, 232, 185, 97)

$Label1 = GUICtrlCreateLabel("Label1", 112, 312, 80, 17)

$Label2 = GUICtrlCreateLabel("Label2", 112, 352, 36, 17)

$Button3 = GUICtrlCreateButton("Pause", 248, 360, 75, 25, 0)

$Button4 = GUICtrlCreateButton("Resume", 328, 360, 75, 25, 0)

GUISetState(@SW_SHOW)

#EndRegion ### END Koda GUI section ###

$iCount = 0

_AdlibEnable("_1",1)

_AdlibEnable("_2",1)

_AdlibEnable("_3",1)

_AdlibEnable("_4",400)

_AdlibEnable("_5",500)

_AdlibEnable("_6",6000)

_AdlibEnable("_7",700)

_AdlibEnable("_8",1)

_AdlibEnable("_9",1000)

_AdlibEnable("_0",2000)

_AdlibActive()

While 1

$nMsg = GUIGetMsg()

Switch $nMsg

Case $GUI_EVENT_CLOSE

Exit

Case $Button3

_AdlibPause(0)

Case $Button4

_AdlibResume(0)

EndSwitch

WEnd

Func _1()

_GUICtrlListBox_AddString($List1, @SEC &"="& Random(0, 9) )

EndFunc

Func _2()

_GUICtrlListBox_AddString($List2, @SEC &"="& Random(9, 0) )

EndFunc

Func _3()

GUICtrlSetData($Progress1, Random(0, 100, 1))

EndFunc

Func _4()

GUICtrlSetData($Slider1, Random(0, 100, 1))

EndFunc

Func _5()

ControlMove("", "", $Button1, Random(0, 18), Random(300, 350))

EndFunc

Func _6()

ControlMove("", "", $Button2, Random(0, 24), Random(336, 352))

EndFunc

Func _7()

_GUICtrlEdit_AppendText($Edit1, "Hellow World, welcome to my world" &@CRLF)

EndFunc

Func _8()

$iCount += 1

GUICtrlSetData($Label1, "count: " & $iCount)

EndFunc

Func _9()

ToolTip("Hello", Random(@DesktopHeight, @DesktopWidth, 1))

EndFunc

Func _0()

ConsoleWrite("The cow barks like a fish" &@lf)

EndFunc

Edited by mrRevoked

Don't bother, It's inside your monitor!------GUISetOnEvent should behave more like HotKeySet()

Share this post


Link to post
Share on other sites
spudw2k

Here's a pretty neat example, what impresses me most is the 0% CPU usage and It's quite fast, and doesn't freeze up the whole script (unless you use a loop)

Cool. It did use CPU on my little lappy though, but changing the time from 1 to 10 remedied that. Fasinating that the adlib func to write to do the ConsoleWrite, buffers the prints when dragging the gui, while the GUI funcs pause. Edited by spudw2k

Share this post


Link to post
Share on other sites
ResNullius

Pretty cool. Reminds me of the adlib manager that ResNullius made, but more dynamic. I did some timing testing and it looks good so far. :mellow: Very nice.

What???

In the way that a powerful lion reminds you of a feeble newborn kitten?

This is way cooler and more then I could ever have hoped to achieve.

Great job jennico!

Share this post


Link to post
Share on other sites
martin

This doesn't look like multithreading; it appears to be no different to using timers.

What happens if one or more of the functions called takes longer to execute than the frequency?

Suppose, as a simple example, you had 2 functions like this

Func fone()
for $n1 = 1 to 9000
 GuiCtrlSetData($lab1,$n)
 sleep(500)
next
EndFunc

Func ftwo()

for $n2 = 1 to 9000
 GuiCtrlSetData($lab2,$n)
 sleep(400)
next

EndFunc

How would you use your udf to run both of those at the same time?

Why would this approach be better for calculating the positions of 9 balls than calculating all nine positions in one function every interval, or having one function which is passed parameters and called 9 times more frequently?

The pause doesn't pause a function it seems to stop the function from being called.

Sorry to be negative but your claims look like misrepresentation to me, I think your title should be Multiple Adlibs and not multitasking.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
jennico

@ martin : you are not that naive, are you ? real multithreading is not possible with AutoIt. this is just an approach. Autoit cannot make coffee either.

The adlib function should be kept simple as it is executed often and during this time the main script is paused.

Also, the time parameter should be used carefully to avoid CPU load.

and:

please don't tell me that there have been made other attempts before, i tried them all. and i know about _Timer_SetTimer and callback, but i think these functions serve different usages.

i intended to avoid a comment like yours, but this kind of nitpicking does not seem to be avoidable.

Why would this approach be better for calculating the positions of 9 balls than calculating all nine positions in one function every interval, or having one function which is passed parameters and called 9 times more frequently?

i think i pointed that out very clearly.

The pause doesn't pause a function it seems to stop the function from being called.

what do you want to say ??? something like : this polar bear is not a polar bear because its color is more greyish than white ??? nitpicking.

this is a very strange comment. :mellow:

j.

Edited by jennico

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
Innovative

This doesn't look like multithreading; it appears to be no different to using timers.

What happens if one or more of the functions called takes longer to execute than the frequency?

Suppose, as a simple example, you had 2 functions like this

Func fone()
for $n1 = 1 to 9000
 GuiCtrlSetData($lab1,$n)
 sleep(500)
next
EndFunc

Func ftwo()

for $n2 = 1 to 9000
 GuiCtrlSetData($lab2,$n)
 sleep(400)
next

EndFunc

How would you use your udf to run both of those at the same time?

Why would this approach be better for calculating the positions of 9 balls than calculating all nine positions in one function every interval, or having one function which is passed parameters and called 9 times more frequently?

The pause doesn't pause a function it seems to stop the function from being called.

Sorry to be negative but your claims look like misrepresentation to me, I think your title should be Multiple Adlibs and not multitasking.

IMO , you shouldn't critisise him like that , it's a load of hard work just to make that .

We should thanks him instead, although i don't understand the concept =)

THANKS BUDDY !

Edited by xVivoCity

Share this post


Link to post
Share on other sites
BrettF

Share this post


Link to post
Share on other sites
Digisoul

jennico Your Rock :mellow:

Its Really gr8888888 Script.

Edited by Digisoul

73 108 111 118 101 65 117 116 111 105 116

Share this post


Link to post
Share on other sites
jennico

real multithreading is not possible with AutoIt. this is just an approach. Autoit cannot make coffee either.

is it so hard to understand ? programming always means simulation. if i post my nine ball game here and i call the post "playing billard with AutoIt", you would still tell me that this is not true, because AutoIt can not play billard ? of course it cannot. it is just a SIMULATION.

even if you run two programs at the same time, this is not really "multitasking", because the CPU can only work on one process at a time, and the others have to wait.

and sorry:

Func fone()
for $n1 = 1 to 9000
GuiCtrlSetData($lab1,$n)
sleep(500)
next
EndFunc

Func ftwo()

for $n2 = 1 to 9000
GuiCtrlSetData($lab2,$n)
sleep(400)
next

EndFunc

who would be so clever to put a sleep in an adlib function, and afterwards he blames my UDF for not working ?

Sleep

--------------------------------------------------------------------------------

Pause script execution.

if you make a script sleep you should not expect it to go on working.

j.


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
jennico

besides that, thank you all for your encouraging.

has anyone found a bug or an idea for more implementations ? i think i could implement a parameter on _AdlibPause that automatically resumes the adlib after a count of ticks. for example.

j.


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
AzKay

"who would be so clever to put a sleep in an adlib function, and afterwards he blames my UDF for not working ?"

Well, In my opinion, if its a "simulation" of multithreading, it should work whether there is a sleep in there or not.


# MY LOVE FOR YOU... IS LIKE A TRUCK- #

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×