Releases: icicleio/icicle
Releases · icicleio/icicle
v0.9.6
Added
- Added
Icicle\execute()
function that takes a callback (may be a normal function, return anAwaitable
, or be a coroutine) and runs the function within a running event loop. This function may be used to initialize and run a program instead of manually creating an initialCoroutine
instance and callingIcicle\Loop\run()
.
Fixed
- Fixed #18 resulting from
stream_select()
on Windows sometimes removing array keys if only a single socket is in the loop. - Fixed a bug in
Icicle\Loop\SelectLoop
that could result in the callback on an IO watcher to be erroneously invoked with$expired
set totrue
ifIo::listen()
is called successively without an event occurring between invocations.
v0.9.5
Changed
- Awaitables are now synchronously resolved. Callbacks are immediately invoked when an awaitable is resolved. Callbacks registered with
then()
,done()
or other methods will invoke the callback immediately if the awaitable has been resolved. This change was made to improve performance in coroutines. If resolving an awaitable in an object, be sure to cleanup the objects state before resolving the awaitable. With this change, methods on the object could be called before the method resolving the awaitable finishes. While some changes were needed within this library and some of the basic Icicle packages, application code built on coroutines should see no effects from this change. - Renamed
signalHandlingEnabled()
toisSignalHandlingEnabled()
inIcicle\Loop\Loop
to be consistent with other method naming conventions. The functionIcicle\Loop\signalHandlingEnabled()
was also renamed toIcicle\Loop\isSignalHandlingEnabled()
. - Immediates are now invoked only if there are no active events in the loop. An active event is one where the event has occurred, but the callback has not yet been invoked. As before, only a single Immediate is invoked before polling streams for data, invoking timers, or checking for signals.
- Cancelled coroutines now continue executing their generator function, allowing coroutines to execute cleanup code in try/catch blocks. As before, if a coroutine is waiting on an awaitable at the time it is cancelled, that awaitable is still cancelled. The cancellation reason is then thrown into the generator.
v0.9.4
Added
- Added
of()
,fail()
,concat()
,zip()
, andrange()
functions to theIcicle\Observable
namespace. See each function for more information. - Added
reduce()
function toIcicle\Observable\Observable
that executes an accumulator function on each emitted value, returning an observable that emits the current accumulated value after each invokation of the accumulator.
Changed
- Passing
null
(now the default argument) toIcicle\Loop\Loop::maxQueueDepth()
orIcicle\Loop\maxQueueDepth()
will return the current max queue depth without modifying it. Icicle\Observable\Emitter
can delegate to another instance ofIcicle\Observable\Observable
by emitting the observable. Values from the emitted observable will then be emitted as though they were emitted by the delegating observable. The$emit
callable will resolve with the return value of the emitted observable.Icicle\Observable\Emitter
now allows multiple coroutines to be created from the$emit
callable simultaneously. This makes no difference for emitters usingyield
with$emit
, but simplifies implementations using$emit
as part of a callback that may be called before the previous value has finished emitting. SeeIcicle\Observable\merge()
for an example of a function that uses$emit
as a callback.- If an awaitable emitted from
Icicle\Observable\Emitter
is rejected, the observable will fail with the exception used to reject the awaitable. Icicle\Observable\observe()
now takes a callable$onDisposed
argument that is invoked with the callable passed to the emitting function if the observable is disposed. This function can be used to remove the callable from the event emitter.
Fixed
- Fixed #14 caused by queued function arguments being retained in the loop until a full tick completed, consuming more memory than necessary. Arguments are now freed immediately after executing each queued function.
v0.9.3
Added
Icicle\Observable\Emitter
gained an optional$onDisposed
parameter on the constructor accepting a callback function that is executed if the observable is disposed (either automatically or explicitly). This callback can either be a regular function, return an awaitable, or a coroutine. If the callback function returns an awaitable or is a coroutine, the observable is not disposed until the awaitable resolves. If the callback throws an exception (or the awaitable rejects), that exception will be used to dispose of the observable.
Changed
- Cancelling a coroutine will no longer throw the cancellation reason into the generator. Generator execution is simply terminated. Repeatedly throwing the exception into the generator caused unpredictable and unexpected behaviors. Use
finally
blocks or cancellation functions on awaitables if it is necessary to clean up state in coroutines. This method is far cleaner and prevents unintentional state-altering code being executed after cancellation. - Cancelled awaitables will now report as pending until any cancellation function has been invoked.
Fixed
- Fixed issue where the coroutine created from a yielded generator in a coroutine would not be cancelled if the parent coroutine was cancelled (issue only affected v0.9.x and v1.x branches).
v0.9.2
Changes
- Watchers now pass the watcher object to the callback function when an event occurs. The watcher object is passed as the last function argument (in the case of timers and immediates, the only argument).
- All watchers now include
setData()
andgetData()
methods for setting and getting data associated with the watcher. Functions creating watchers have an optional$data
parameter that can be used to set the data associated with a watcher when it is created. - The functions creating timers and immediates no longer accept a variadic list of arguments to pass to the callback invoked by the timer or immediate. Instead the timer or immediate watcher object is passed to the callback. Use
getData()
andsetData()
on the watcher for passing data to the callback.
v0.9.1
New Features
Icicle\Loop\Watcher\Timer
gained anagain()
method that will restart the timer as though it were just started even if the timer is currently pending.Icicle\Loop\poll()
andIcicle\Loop\await()
now have a third parameter that if true (defaults to false) will create a persistent IO watcher object that will remain active oncelisten()
is called untilcancel()
is called on the watcher.Icicle\Loop\Watcher\Io
gained aisPersistent()
method returning a boolean.
Changes
- Dropped support for the
event
andlibevent
extensions. These extensions have been replaced by theev
extension and are no longer being actively developed. - Cancelling a coroutine will throw the cancellation reason into the generator and cancel any yielded awaitables.
Bug Fixes
- Fixed issue where disposing of an observable would not throw the disposal reason from
ObservableIterator::getReturn()
.
v0.9.0
Changes
- All interface names have been changed to remove the
Interface
suffix. Most interfaces simply had the suffix removed, but there are a few exceptions - more below. - Promises are now Awaitables
- The
Icicle\Promise
namespace has been renamed toIcicle\Awaitable
.Icicle\Promise\PromiseInterface
is nowIcicle\Awaitable\Awaitable
. Icicle\Awaitable\Promise
(previouslyIcicle\Promise\Promise
) now extends a new classIcicle\Awaitable\Future
that implementsIcicle\Awaitable\Awaitable
.Future
uses protected methods to resolve the awaitable, so it can be extended to create awaitables that are resolved in different ways. The functionality ofPromise
has not changed.Icicle\Coroutine\Coroutine
now also extendsIcicle\Awaitable\Future
. The functionality ofCoroutine
has not changed, but it should be faster to create aCoroutine
object.Icicle\Coroutine\CoroutineInterface
has been removed.
- The
- The
Icicle\Loop\Events
namespace was renamed toIcicle\Loop\Watcher
. Interfaces in the namespace were removed exceptEventInterface
which was renamed toWatcher
. Icicle\Loop\Events\SocketEvent
was renamed toIcicle\Loop\Watcher\Io
since more than just 'sockets' can be used.Icicle\Coroutine\create()
no longer throws if the callback throws or returns a promise, instead it returns a rejected coroutine.Icicle\Awaitable\Awaitable::timeout()
(previouslyIcicle\Promise\PromiseInterface::timeout()
) now takes a callback function that is invoked if the parent awaitable is not resolved in the given timeout. The promise returned from this method is resolved by the callback function. This callback function can still cancel the parent promise if desired or perform any other action.- Rejecting an awaitable now requires an exception instance.
Icicle\Awaitable\Awaitable::cancel()
(previouslyIcicle\Promise\PromiseInterface::cancel()
now requires an exception instance or null. If null, an instance ofIcicle\Awaitable\Exception\CancelledException
is used.Icicle\Awaitable\Awaitable::timeout()
(previouslyIcicle\Promise\PromiseInterface::timeout()
now takes a callable or null as the second argument. The awaitable returned fromtimeout()
is resolved by the callable or rejected with an instance ofIcicle\Awaitable\Exception\TimeoutException
if no callable is given.
New Features
- Added observables that represent asynchronous collections. Observables implement
Icicle\Observable\Observable
and include array-like methods includingObservable::map()
andObservable::filter()
. Observables can be iterated over asynchronously in a coroutine using the iterator returned fromObservable::getIterator()
. See the example inexamples/observable.php
and the documentation (work-in-progress) for more information. Icicle\Awaitable\Delayed
was added as a publicly resolvable awaitable. This type of awaitable should not be returned from public APIs, but rather only used internally within a class or Coroutine to create an awaitable that can be resolved later. So in other words, a class method or function should never return aDelayed
. In general, methods and functions should not be returning awaitables as part of their public API. The public API should consist of Generators that can be used as Coroutines.Icicle\Awaitable\Awaitable
now has a methoduncancellable()
that returns an awaitable that cannot be cancelled (thecancel()
method is a no-op).
v0.8.3
New Features
- Added
Coroutine\run()
function that may be used to create an initial coroutine that runs the rest of the application. This function should not be called in a running event loop. - All loop events can now be referenced/unreferenced like timers using the
reference()
andunreference()
methods on event objects. Only referenced events will prevent an event loop from exiting therun()
method. Signal events are created as unreferenced, while all other events are created as referenced.
v0.8.2
v0.8.1
New Features
- Added
Icicle\Loop\EvLoop
supporting theev
extension. This loop is now the default event loop used if theev
extension is available. Icicle\Promise\map()
now accepts any number of arrays likearray_map()
, passing an element of each array as an argument to the callback function.
Bug Fixes
- Coroutines are paused immediately upon cancellation to ensure execution does not continue after cancellation.