Created
May 24, 2013 12:31
-
-
Save Ekstazi/5643180 to your computer and use it in GitHub Desktop.
Haxe callbacks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mysql.common; | |
/** | |
* ... | |
* @author Ekstazi | |
*/ | |
/** | |
* @todo | |
*/ | |
class Callbacks<T> | |
{ | |
/** | |
* указывает, что список колбэков может быть выполнен только единожды, | |
* второй и последующие вызовы метода fire() будут безрезультатны | |
* (как это сделано в объекте deferred), если этот флаг не указан, | |
* то можно несколько раз вызывать метод fire(). | |
*/ | |
public static var ONCE = 1; | |
/** | |
* указывает, что необходимо запоминать параметры последнего вызова метода fire() | |
* (и выполнения колбэков из списка) и немедленно выполнять добавляемые колбэки | |
* с соответствующими параметрами, если они добавляются уже после вызова метода fire() | |
* (как это сделано в объекте deferred). | |
*/ | |
public static var MEMORY = 2; | |
/** | |
* указывает, что каждый колбэк может быть добавлен в список только один раз, | |
* повторная попытка добавить колбэк в список ни к чему ни приведёт. | |
*/ | |
public static var UNIQUE = 4; | |
/** | |
* указывает, что нужно прекратить выполнение колбэков из списка, | |
* если какой-то из них вернул false, в пределах текущей сессии вызова fire(). | |
* Следующий вызов метода fire() начинает новую сессию выполнения списка колбэков, | |
* и они будут выполняться опять до тех пор, пока один из списка не вернёт false | |
* либо пока не закончатся. | |
*/ | |
public static var STOP_ON_FALSE = 8; | |
private var _callbacks:Array<T->Dynamic>; | |
private var _fired:Bool; | |
private var _iterrupted:Bool; | |
private var _flags:UInt; | |
private var _params:Array<T>; | |
public var isActive:Bool; | |
public var isLocked:Bool; | |
public function new(flags:UInt=0) | |
{ | |
isActive = true; | |
empty(); | |
_flags = flags; | |
} | |
/** | |
* Добавляет в список колбэки, | |
* можно одновременно передавать в аргументах этого метода несколько функций с помощью массива | |
* или всего одну функцию | |
* @param ?closure | |
* @param ?closures | |
*/ | |
public function add(?closure:T->Dynamic,?closures:Array<T->Dynamic>) | |
{ | |
if (!isActive) | |
return this; | |
if(closure!=null){ | |
if (_flags & UNIQUE == 0 || !has(closure)) { | |
_callbacks.push(closure); | |
if (_fired && _flags & MEMORY > 0) { | |
for(i in _params) | |
execute(i,closure); | |
} | |
} | |
} | |
if (closures != null) { | |
Lambda.iter(closures, function(f:T->Dynamic) { add(f); } ); | |
} | |
return this; | |
} | |
/** | |
* Удаляет колбэки из списка, причем даже если колбэк был добавлен дважды, | |
* удаление его произойдёт с обеих позиций. Т.о. если вызвать метод удаления | |
* некоторого колбэка из списка, то можно быть уверенным, что его в списке больше нет, | |
* сколько бы раз его не добавляли. Можно передавать несколько функций одновременно | |
* как массив. | |
* @param ?closure | |
* @param ?closures | |
*/ | |
public function remove(?closure:T->Dynamic,?closures:Array<T->Dynamic>) | |
{ | |
if (!isActive) | |
return this; | |
if(closure!=null){ | |
while (_callbacks.remove(closure)) { }; | |
} | |
if (closures != null) { | |
Lambda.iter(closures, function(f:T->Dynamic) { remove(f); } ); | |
} | |
return this; | |
} | |
/** | |
* Проверяет, есть ли указанная функция в списке колбэков | |
* @param closure | |
* @return Bool | |
*/ | |
public function has(closure:T->Dynamic):Bool | |
{ | |
if (!isActive) | |
return false; | |
return Lambda.has(_callbacks, closure); | |
} | |
/** | |
* очищает список колбэков и сбрасывает состояние | |
*/ | |
public function empty() | |
{ | |
if (!isActive) | |
return this; | |
_callbacks = []; | |
_fired = isLocked = _iterrupted = false; | |
return this; | |
} | |
/** | |
* Фиксирует текущее состояние объекта callbacks относительно параметров | |
* и состояния выполнения списка колбэков. Этот метод актулен при использовании | |
* флага memory и предназначен для блокирования только последующих вызовов fire(), | |
* в остальных случаях он равносилен вызову disable(). | |
*/ | |
public function lock() | |
{ | |
isLocked = true; | |
if (!_fired) | |
isActive = false; | |
return this; | |
} | |
public function unlock() | |
{ | |
isLocked = false; | |
if (_flags & MEMORY == 0 || !_fired) | |
isActive = true; | |
return this; | |
} | |
/** | |
* «отключает» объект callbacks, все действия с ним будут безрезультатны. | |
* При этом перестают работать вообще все методы: add — ни к чему не приводит, | |
* has — всегда возвращает false и пр. | |
*/ | |
public function disable() | |
{ | |
isActive = false; | |
return this; | |
} | |
/** | |
* Включает все методы объекта | |
*/ | |
public function enable() | |
{ | |
isActive = true; | |
return this; | |
} | |
private function execute(arg:T,closure:T->Dynamic) | |
{ | |
if (_iterrupted) | |
return false; | |
var r:Dynamic = closure(arg); | |
if (_flags & STOP_ON_FALSE > 0 && Std.is(r, Bool) && false == cast r) { | |
_iterrupted = true; | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Запускает выполнение всех колбэков в списке с аргументом этого метода. | |
* @param arg | |
*/ | |
public function fire(arg:T) | |
{ | |
if (isLocked || !isActive || _fired && _flags & ONCE > 0 ) | |
return this; | |
_iterrupted = false; | |
Lambda.foreach(_callbacks, callback(execute,arg)); | |
_fired = true; | |
if(_flags & MEMORY>0) | |
_params.push(arg); | |
return this; | |
} | |
public function fired() | |
{ | |
return _fired; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment