Tarantool CE/EE Documentation portal logo
Support
Updated at July 17, 2026   02:08 PM

Module fiber

Overview

With the fiber module, you can:

  • Create, run, and manage fibers.
  • Send and receive messages between different processes (i.e. different connections, sessions, or fibers) via channels.
  • Use a synchronization mechanism for fibers, similar to "condition variables" and similar to operating-system functions, such as pthread_cond_wait() plus pthread_cond_signal().

Index

Below is a list of all fiber functions and members.

Name

Use

Fibers

fiber.create()

Create and start a fiber

fiber.new()

Create but do not start a fiber

fiber.self()

Get a fiber object

fiber.find()

Get a fiber object by ID

fiber.sleep()

Make a fiber go to sleep

fiber.yield()

Yield control

fiber.status()

Get the current fiber's status

fiber.info()

Get information about all fibers

fiber.top()

Return a table of alive fibers and show their CPU consumption

fiber.kill()

Cancel a fiber

fiber.testcancel()

Check if the current fiber has been cancelled

fiber.set_max_slice()

Set the default maximum slice for all fibers

fiber.set_slice()

Set a slice for the current fiber execution

fiber.extend_slice()

Extend a slice for the current fiber execution

fiber.check_slice()

Check whether a slice for the current fiber is over

fiber.time()

Get the system time in seconds

fiber.time64()

Get the system time in microseconds

fiber.clock()

Get the monotonic time in seconds

fiber.clock64()

Get the monotonic time in microseconds

Fiber object

fiber_object:id()

Get a fiber's ID

fiber_object:name()

Get a fiber's name

fiber_object:name(name)

Set a fiber's name

fiber_object:status()

Get a fiber's status

fiber_object:cancel()

Cancel a fiber

fiber_object.set_max_slice()

Set a fiber's maximum slice

fiber_object.storage

Local storage within the fiber

fiber_object:set_joinable()

Make it possible for a new fiber to join

fiber_object:join()

Wait for a fiber's state to become 'dead'

Channels

fiber.channel()

Create a communication channel

channel_object:put()

Send a message via a channel

channel_object:close()

Close a channel

channel_object:get()

Fetch a message from a channel

channel_object:is_empty()

Check if a channel is empty

channel_object:count()

Count messages in a channel

channel_object:is_full()

Check if a channel is full

channel_object:has_readers()

Check if an empty channel has any readers waiting

channel_object:has_writers()

Check if a full channel has any writers waiting

channel_object:is_closed()

Check if a channel is closed

Example

A useful example about channels

Condition variables

fiber.cond()

Create a condition variable

cond_object:wait()

Make a fiber go to sleep until woken by another fiber

cond_object:signal()

Wake up a single fiber

cond_object:broadcast()

Wake up all fibers

Example

A useful example about condition variables

Fibers

A fiber is a set of instructions that are executed with cooperative multitasking. The fiber module enables you to create a fiber and associate it with a user-supplied function called a fiber function.

A fiber has the following possible states: running, suspended, ready, or dead. A program with fibers is, at any given time, running only one of its fibers. This running fiber only suspends its execution when it explicitly yields control to another fiber that is ready to execute.

When the fiber function ends, the fiber ends and becomes dead. If required, you can cancel a running or suspended fiber. Another useful capability is limiting a fiber execution time for long-running operations.

Create a fiber

To create a fiber, call one of the following functions:

  • fiber.create() creates a fiber and runs it immediately. The initial fiber state is running.
  • fiber.new() creates a fiber but does not start it. The initial fiber state is ready. You can join such fibers by calling the fiber_object:join() function and get the result returned by the fiber's function.

Yield control

Yield is an action that occurs in a cooperative environment that transfers control of the thread from the current fiber to another fiber that is ready to execute. The fiber module provides the following functions that yield control to another fiber explicitly:

  • fiber.yield() yields control to the scheduler.
  • fiber.sleep() yields control to the scheduler and sleeps for the specified number of seconds.

Cancel a fiber

To cancel a fiber, use the fiber_object.cancel function. You can also call fiber.kill() to locate a fiber by its numeric ID and cancel it.

Limit execution time

If a fiber works too long without yielding control, you can use a fiber slice to limit its execution time. The fiber_slice_default compat option controls the default value of the maximum fiber slice.

There are two slice types: a warning and an error slice.

  • When a warning slice is over, a warning message is logged, for example:

    fiber has not yielded for more than 0.500 seconds
  • When an error slice is over, the fiber is cancelled and the FiberSliceIsExceeded error is thrown:

    FiberSliceIsExceeded: fiber slice is exceeded

    Control is passed to another fiber that is ready to execute.

The fiber slice is checked by all functions operating on spaces and indexes, such as index_object.select(), space_object.replace(), and so on. You can also use the fiber.check_slice() function in application code to check whether the slice for the current fiber is over.

The following functions override the the default value of the maximum fiber slice:

The maximum slice is set when a fiber wakes up. This might be its first run or wake up after fiber.yield().

You can change or increase the slice for a current fiber's execution using the following functions:

Note that the specified values don't affect a fiber's execution after fiber.yield().

Information about fibers

To get information about all fibers or a specific fiber, use the following functions:

Garbage collection

Like all Lua objects, dead fibers are garbage collected. The Lua garbage collector frees pool allocator memory owned by the fiber, resets all fiber data, and returns the fiber (now called a fiber carcass) to the fiber pool. The carcass can be reused when another fiber is created.

A fiber has all the features of a Lua coroutine and all the programming concepts that apply to Lua coroutines apply to fibers as well. However, Tarantool has made some enhancements for fibers and has used fibers internally. So, although the use of coroutines is possible and supported, the use of fibers is recommended.

API reference

create(function [, function-arguments])

Create and start a fiber. The fiber is created and begins to run immediately.

Parameters:

  • function — the function to be associated with the fiber

  • function-arguments — arguments to be passed to the function

Returns

created fiber object

Return type

userdata

Example:

The script below shows how to create a fiber using fiber.create:

-- app.lua --fiber = require('fiber')function greet(name)    print('Hello, '..name)endgreet_fiber = fiber.create(greet, 'John')print('Fiber already started')
Example

The following output should be displayed after running app.lua:

$ tarantool app.luaHello, JohnFiber already started

new(function [, function-arguments])

Create a fiber but do not start it. The created fiber starts after the fiber creator (that is, the job that is calling fiber.new()) yields. The initial fiber state is ready.

You can join fibers created using fiber.new by calling the fiber_object:join() function and get the result returned by the fiber's function. To join the fiber, you need to make it joinable using fiber_object:set_joinable().

  • function — the function to be associated with the fiber

  • function-arguments — arguments to be passed to the function

Returns

created fiber object

Return type

userdata

Example:

The script below shows how to create a fiber using fiber.new:

-- app.lua --fiber = require('fiber')function greet(name)    print('Hello, '..name)endgreet_fiber = fiber.new(greet, 'John')print('Fiber not started yet')

The following output should be displayed after running app.lua:

$ tarantool app.luaFiber not started yetHello, John

self()

Returns

fiber object for the currently scheduled fiber.

Return type

userdata

Example:

tarantool> fiber.self()---- status: running  name: interactive  id: 101...
Example

find(id)

Parameters:

  • id — numeric identifier of the fiber.

Returns

fiber object for the specified fiber.

Return type

userdata

Example:

tarantool> fiber.find(101)---- status: running  name: interactive  id: 101...
Example

sleep(time)

Yield control to the scheduler and sleep for the specified number of seconds. Only the current fiber can be made to sleep.

Parameters:

  • time — number of seconds to sleep.

Exception : see the Example of yield failure.

Example:

The increment function below contains an infinite loop that adds 1 to the counter global variable. Then, the current fiber goes to sleep for period seconds. sleep causes an implicit fiber.yield().

-- app.lua --fiber = require('fiber')counter = 0function increment(period)    while true do        counter = counter + 1        fiber.sleep(period)    endendincrement_fiber = fiber.create(increment, 2)require('console').start()
Example

After running the script above, print the information about the fiber: a fiber ID, its status, and the counter value.

tarantool> print('ID: ' .. increment_fiber:id() .. '\nStatus: ' .. increment_fiber:status() .. '\nCounter: ' .. counter)ID: 104Status: suspendedCounter: 8---...

Then, cancel the fiber and print the information about the fiber one more time. This time the fiber status is dead.

tarantool> increment_fiber:cancel()---...tarantool> print('ID: ' .. increment_fiber:id() .. '\nStatus: ' .. increment_fiber:status() .. '\nCounter: ' .. counter)ID: 104Status: deadCounter: 12---...

yield()

Yield control to the scheduler. Equivalent to fiber.sleep(0).

Exception : see the Example of yield failure.

Example:

In the example below, two fibers are associated with the same function. Each fiber yields control after printing a greeting.

-- app.lua --fiber = require('fiber')function greet()    while true do        print('Enter a name:')        name = io.read()        print('Hello, '..name..'. I am fiber '..fiber.id())        fiber.yield()    endendfor i = 1, 2 do    fiber_object = fiber.create(greet)    fiber_object:cancel()end
Example

The output might look as follows:

$ tarantool app.luaEnter a name:JohnHello, John. I am fiber 104Enter a name:JaneHello, Jane. I am fiber 105

status([fiber_object])

Return the status of the current fiber. If the fiber_object is passed, return the status of the specified fiber.

Parameters:

  • fiber_object — (optional) the fiber object

Returns

the status of fiber. One of: dead, suspended, or running.

Return type

string

Example:

tarantool> fiber.status()---- running...
Example

info({[backtrace/bt]})

Return information about all fibers.

Parameters:

  • backtrace (boolean) — show backtrace. Default: true. Set to false to show less information (symbol resolving can be expensive).

  • bt (boolean) — same as backtrace, but with lower priority.

Returns

number of context switches (csw), backtrace, total memory, used memory, fiber ID (fid), fiber name. If fiber.top is enabled or Tarantool was built with ENABLE_FIBER_TOP, processor time (time) is also returned.

Return type

table

Return values explained

  • csw – number of context switches.

  • backtrace, bt – each fiber's stack trace, showing where it originated and what functions were called.

  • memory:

    • total – total memory occupied by the fiber as a C structure, its stack, etc.
    • used – actual memory used by the fiber.

time – duplicates the "time" entry from fiber.top().cpu for each fiber.

: Only shown if fiber.top is enabled.

Example:

tarantool> fiber.info({ bt = true })---- 101:    csw: 1    backtrace:    - C: '#0  0x5dd130 in lbox_fiber_id+96'    - C: '#1  0x5dd13d in lbox_fiber_stall+13'    - L: stall in =[C] at line -1    - L: (unnamed) in @builtin/fiber.lua at line 59    - C: '#2  0x66371b in lj_BC_FUNCC+52'    - C: '#3  0x628f28 in lua_pcall+120'    - C: '#4  0x5e22a8 in luaT_call+24'    - C: '#5  0x5dd1a9 in lua_fiber_run_f+89'    - C: '#6  0x45b011 in fiber_cxx_invoke(int (*)(__va_list_tag*), __va_list_tag*)+17'    - C: '#7  0x5ff3c0 in fiber_loop+48'    - C: '#8  0x81ecf4 in coro_init+68'    memory:    total: 516472    used: 0    time: 0    name: lua    fid: 101  102:    csw: 0    backtrace:    - C: '#0  (nil) in +63'    - C: '#1  (nil) in +63'    memory:    total: 516472    used: 0    time: 0    name: on_shutdown    fid: 102...
Example

top()

Show all alive fibers and their CPU consumption.

Returns

a table with two entries: cpu and cpu_misses

cpu itself is a table whose keys are strings containing fiber ids and names. The three metrics available for each fiber are:

  1. instant (in percent), which indicates the share of time the fiber was executing during the previous event loop iteration.

  2. average (in percent), which is calculated as an exponential moving average of instant values over all the previous event loop iterations.

  3. time (in seconds), which estimates how much CPU time each fiber spent processing during its lifetime.

    The time entry is also added to each fiber's output in fiber.info() (it duplicates the time entry from fiber.top().cpu per fiber).

    Note that time is only counted while fiber.top() is enabled.

cpu_misses indicates the number of times the TX thread detected it was rescheduled on a different CPU core during the last event loop iteration. fiber.top() uses the CPU timestamp counter to measure each fiber's execution time. However, each CPU core may have its own counter value (you can only rely on counter deltas if both measurements were taken on the same core, otherwise the delta may even get negative). When the TX thread is rescheduled to a different CPU core, Tarantool just assumes the CPU delta was zero for the latest measurement. This lowers the precision of our computations, so the bigger cpu misses value the lower the precision of fiber.top() results.

Example:

tarantool> fiber.top()---- cpu:    107/lua:      instant: 30.967324490456      time: 0.351821993      average: 25.582738345233    104/lua:      instant: 9.6473633128437      time: 0.110869897      average: 7.9693406131877    101/on_shutdown:      instant: 0      time: 0      average: 0    103/lua:      instant: 9.8026528631511      time: 0.112641118      average: 18.138387232255    106/lua:      instant: 20.071174377224      time: 0.226901357      average: 17.077908441831    102/interactive:      instant: 0      time: 9.6858e-05      average: 0    105/lua:      instant: 9.2461986412164      time: 0.10657528      average: 7.7068458630827    1/sched:      instant: 20.265286315108      time: 0.237095335      average: 23.141537169257  cpu_misses: 0...

Notice that by default new fibers created due to fiber.create are named 'lua' so it is better to set their names explicitly via fiber_object:name('name').

There are several system fibers in fiber.top() output that might be useful:

  • sched is a special system fiber. It schedules tasks to other fibers, if any, and also handles some libev events.

    It can have high instant and average values in fiber.top() output in two cases:

    • The instance has almost no load - then practically only sched is executing, and the other fibers are sleeping. So relative to the other fibers, sched may have almost 100% load.
    • sched handles a large number of system events. This should not cause performance problems.
  • main fibers process requests that come over the network (iproto requests). There are several such fibers, and new ones are created if needed. When a new request comes in, a free fiber takes it and executes it. The request can be a typical select/replace/delete/insert or a function call. For example, conn:eval() or conn:call().

kill(id)

Locate a fiber by its numeric ID and cancel it. In other words, fiber.kill() combines fiber.find() and fiber_object:cancel().

Parameters:

  • id — the ID of the fiber to be cancelled.

Exception : the specified fiber does not exist or cancel is not permitted.

Example:

tarantool> fiber.kill(fiber.id()) -- kill self, may make program end---- error: fiber is cancelled...
Example

testcancel()

Check if the current fiber has been cancelled and throw an exception if this is the case.

Example:

tarantool> fiber.testcancel()---- error: fiber is cancelled...

set_max_slice(slice)

Set the default maximum slice for all fibers. A fiber slice limits the time period of executing a fiber without yielding control.

Parameters:

  • slice (number/table) — a fiber slice, which can one of the following:

  • a time period (in seconds) that specifies the error slice. Example: fiber.set_max_slice(3).

  • a table that specifies the warning and error slices (in seconds). Example: fiber.set_max_slice({warn = 1.5, err = 3}).

Example:

The example below shows how to use set_max_slice to limit the slice for all fibers. fiber.check_slice() is called inside a long-running operation to determine whether a slice for the current fiber is over.

-- app.lua --fiber = require('fiber')clock = require('clock')fiber.set_max_slice({warn = 1.5, err = 3})time = clock.monotonic()function long_operation()    while clock.monotonic() - time < 5 do        fiber.check_slice()        -- Long-running operation ⌛⌛⌛ --    endendlong_operation_fiber = fiber.create(long_operation)
Example

The output should look as follows:

$ tarantool app.luafiber has not yielded for more than 1.500 secondsFiberSliceIsExceeded: fiber slice is exceeded

set_slice(slice)

Set a slice for the current fiber execution. A fiber slice limits the time period of executing a fiber without yielding control.

Parameters:

  • slice (number/table) — a fiber slice, which can one of the following:

  • a time period (in seconds) that specifies the error slice. Example: fiber.set_slice(3).

  • a table that specifies the warning and error slices (in seconds). Example: fiber.set_slice({warn = 1.5, err = 3}).

Example:

The example below shows how to use set_slice to limit the slice for the current fiber execution. fiber.check_slice() is called inside a long-running operation to determine whether a slice for the current fiber is over.

-- app.lua --fiber = require('fiber')clock = require('clock')time = clock.monotonic()function long_operation()    fiber.set_slice({warn = 1.5, err = 3})    while clock.monotonic() - time < 5 do        fiber.check_slice()        -- Long-running operation ⌛⌛⌛ --    endendlong_operation_fiber = fiber.create(long_operation)
Example

The output should look as follows.

$ tarantool app.luafiber has not yielded for more than 1.500 secondsFiberSliceIsExceeded: fiber slice is exceeded

extend_slice(slice)

Extend a slice for the current fiber execution. For example, if the default error slice is set using fiber.set_max_slice() to 3 seconds, extend_slice(1) extends the error slice to 4 seconds.

Parameters:

  • slice (number/table) — a fiber slice, which can one of the following:

  • a time period (in seconds) that specifies the error slice. Example: fiber.extend_slice(1).

  • a table that specifies the warning and error slices (in seconds). Example: fiber.extend_slice({warn = 0.5, err = 1}).

Example:

The example below shows how to use extend_slice to extend the slice for the current fiber execution. The default fiber slice is set using set_max_slice.

-- app.lua --fiber = require('fiber')clock = require('clock')fiber.set_max_slice({warn = 1.5, err = 3})time = clock.monotonic()function long_operation()    fiber.extend_slice({warn = 0.5, err = 1})    while clock.monotonic() - time < 5 do        fiber.check_slice()        -- Long-running operation ⌛⌛⌛ --    endendlong_operation_fiber = fiber.create(long_operation)
Example

The output should look as follows.

$ tarantool app.luafiber has not yielded for more than 2.000 secondsFiberSliceIsExceeded: fiber slice is exceeded

FiberSliceIsExceeded is thrown after 4 seconds.

check_slice()

Check whether a slice for the current fiber is over. A fiber slice limits the time period of executing a fiber without yielding control.

Example:

See the examples for the following functions:

time()

Returns

current system time (in seconds since the epoch) as a Lua number. The time is taken from the event loop clock, which makes this call very cheap, but still useful for constructing artificial tuple keys.

Return type

number

Example:

tarantool> fiber.time(), fiber.time()---- 1448466279.2415- 1448466279.2415...
Example

time64()

Returns

current system time (in microseconds since the epoch) as a 64-bit integer. The time is taken from the event loop clock.

Return type

cdata (ctype<int64_t>)

Example:

tarantool> fiber.time(), fiber.time64()---- 1448466351.2708- 1448466351270762...
Example

clock()

Get the monotonic time in seconds. It is better to use fiber.clock() for calculating timeouts instead of fiber.time() because fiber.time() reports real time so it is affected by system time changes.

Returns

a floating-point number of seconds, representing elapsed wall-clock time since some time in the past that is guaranteed not to change during the life of the process

Return type

number

Example:

tarantool> start = fiber.clock()---...tarantool> print(start)248700.58805---...tarantool> print(fiber.time(), fiber.time()-start)1600785979.8291 1600537279.241---...
Example

clock64()

Same as fiber.clock() but in microseconds.

Returns

a number of seconds as 64-bit integer, representing elapsed wall-clock time since some time in the past that is guaranteed not to change during the life of the process

Return type

cdata (ctype<int64_t>)

fiber_object

id()

Parameters:

Returns

ID of the fiber.

Return type

number

fiber.self():id() can also be expressed as fiber.id().

Example:

tarantool> fiber_object = fiber.self()---...tarantool> fiber_object:id()---- 101...

name()

Returns

name of the fiber.

Return type

string

fiber.self():name() can also be expressed as fiber.name().

Example:

tarantool> fiber.self():name()---- interactive...

name(name[, options])

Change the fiber name. By default a Tarantool server's interactive-mode fiber is named 'interactive' and new fibers created due to fiber.create are named 'lua'. Giving fibers distinct names makes it easier to distinguish them when using fiber.info and fiber.top(). Max length is 255.

  • fiber_object — generally this is an object referenced in the return from fiber.create or fiber.self or fiber.find

  • name (string) — the new name of the fiber.

  • options — none

  • truncate=true – truncates the name to the max length if it is too long. If this option is false (the default), fiber.name(new_name) fails with an exception if a new name is too long. The name length limit is 255 (since version 2.4.1).

Returns

nil

Example:

tarantool> fiber.self():name('non-interactive')---...

status()

Return the status of the specified fiber.

Returns

the status of fiber. One of: "dead", "suspended", or "running".

Return type

string

fiber.self():status() can also be expressed as fiber.status().

Example:

tarantool> fiber.self():status()---- running...

cancel()

Send a cancellation request to the fiber. Running and suspended fibers can be cancelled. After a fiber has been cancelled, attempts to operate on it cause errors, for example, fiber_object:name() causes error: the fiber is dead. But a dead fiber can still report its ID and status.

Cancellation is asynchronous. Use fiber_object:join() to wait for the cancellation to complete. After fiber_object:cancel() is called, the fiber may or may not check whether it was cancelled. If the fiber does not check it, it cannot ever be cancelled.

Returns

nil

Possible errors: cancel is not permitted for the specified fiber object.

Example:

See the fiber.sleep() example.

set_max_slice(slice)

Set a fiber's maximum slice. A fiber slice limits the time period of executing a fiber without yielding control.

  • slice (number/table) — a fiber slice, which can one of the following:

  • a time period (in seconds) that specifies the error slice. Example: long_operation_fiber.set_max_slice(3).

  • a table that specifies the warning and error slices (in seconds). Example: long_operation_fiber.set_max_slice({warn = 1.5, err = 3}).

Example:

The example below shows how to use set_max_slice to limit the fiber slice. fiber.check_slice() is called inside a long-running operation to determine whether a slice for the fiber is over.

``[ lua – app.lua – fiber = require('fiber') clock = require('clock')

time = clock.monotonic() function long_operation() while clock.monotonic() - time]( 5 do fiber.check_slice() – Long-running operation ⌛⌛⌛ – end end

long_operation_fiber = fiber.new(long_operation) long_operation_fiber:set_max_slice({warn = 1.5, err = 3})

The output should look as follows.``` bash$ tarantool app.luafiber has not yielded for more than 1.500 secondsFiberSliceIsExceeded: fiber slice is exceeded

storage

A local storage within the fiber. It is a Lua table created when it is first accessed. The storage can contain any number of named values, subject to memory limitations. Naming may be done with {fiber_object}.storage.{name} or {fiber_object}.storage['{name}']. or with a number {fiber_object}.storage[{number}]. Values may be either numbers or strings.

fiber.storage is destroyed when the fiber is finished, regardless of how is it finished -- via {fiber_object}:cancel(), or the fiber's function did 'return'. Moreover, the storage is cleaned up even for pooled fibers used to serve IProto requests. Pooled fibers never really die, but nonetheless their storage is cleaned up after each request. That makes possible to use fiber.storage as a full featured request-local storage. This behavior is implemented in versions `2.2.3 </release/2.2.3), 2.3.2, 2.4.1, and all later versions.

This storage may be created for a fiber, no matter how the fiber itself is created -- from C or from Lua. For example, a fiber can be created in C using fiber_new(), then it can insert into a space, which has Lua on_replace triggers, and one of the triggers can create fiber.storage. That storage is deleted when the fiber is stopped.

Example:

The example below shows how to save the last entered name in a fiber storage and get this value before cancelling a fiber.

– app.lua –fiber = require('fiber')function greet()    while true do        print('Enter a name:')        name = io.read()        if name ~= 'bye' then            fiber.self().storage.name = name            print('Hello, ' .. name)        else            print('Goodbye, ' .. fiber.self().storage['name'])            fiber.self():cancel()        end    endendfiber_object = fiber.create(greet)

The output might look as follows:

$ tarantool app.luaEnter a name:JohnHello, JohnEnter a name:JaneHello, JaneEnter a name:byeGoodbye, Jane

See also box.session.storage.

set_joinable(is_joinable)

Make a fiber joinable. A joinable fiber can be waited for using fiber_object:join().

The best practice is to call fiber_object:set_joinable() before the fiber function begins to execute because otherwise the fiber could become dead before fiber_object:set_joinable() takes effect. The usual sequence could be:

  1. Call fiber.new() instead of fiber.create() to create a new fiber_object.

    Do not yield at this point, because that will cause the fiber function to begin.

  2. Call fiber_object:set_joinable(true) to make the new fiber_object joinable.

    Now it is safe to yield.

  3. Call fiber_object:join().

    Usually fiber_object:join() should be called, otherwise the fiber's status may become 'suspended' when the fiber function ends, instead of 'dead'.

Parameters:

  • is_joinable (boolean) — the boolean value that specifies whether the fiber is joinable

Returns

nil

Example:

See the fiber_object.join() example.

join([timeout])

Join a fiber. Joining a fiber enables you to get the result returned by the fiber's function.

Joining a fiber runs the fiber's function and waits until the fiber's status is dead. Normally a status becomes dead when the function execution finishes. Joining the fiber causes a yield, therefore, if the fiber is currently in the suspended state, execution of its fiber function resumes.

Note that joining a fiber works only if the fiber is created using fiber.new() and is made joinable using fiber_object:set_joinable().

  • timeout (number) — maximum number of seconds to wait for the completion of the fiber. Default: infinity.

Returns

none

The join method returns two values:

  • The boolean value that indicates whether the join is succeeded because the fiber's function ended normally.
  • The return value of the fiber's function.

If the first value is false, then the join succeeded because the fiber's function ended abnormally and the second result has the details about the error, which one can unpack in the same way that one unpacks a pcall result.

Return type

boolean + result type, or boolean + struct error

Possible errors: the fiber is already joined by concurrent fiber:join().

Example:

The example below shows how to get the result returned by the fiber's function.

fiber = require('fiber')function add(a, b)    return a + bendadd_fiber = fiber.new(add, 5, 6)add_fiber:set_joinable(true)is_success, result = add_fiber:join()print('Is successful: '.. tostring(is_success))print('Returned value: '..result)

The output should look as follows.

$ tarantool app.luaIs successful: trueReturned value: 11

Example of yield failure

Warning: yield() and any function which implicitly yields (such as sleep()) can fail (raise an exception).

For example, this function has a loop that repeats until cancel() happens. The last thing that it will print is 'before yield', which demonstrates that yield() failed, the loop did not continue until testcancel() failed.

fiber = require('fiber')function function_name()  while true do    print('before testcancel')    fiber.testcancel()    print('before yield')    fiber.yield()  endendfiber_object = fiber.create(function_name)fiber.sleep(.1)fiber_object:cancel()

Channels

Call fiber.channel() to create and get a new channel object.

Call the other routines, via channel, to send messages, receive messages, or check channel status.

Message exchange is synchronous. The Lua garbage collector will mark or free the channel when no one is using it, as with any other Lua object. Use object-oriented syntax, for example, channel:put(message) rather than fiber.channel.put(message).

channel([capacity])

Create a new communication channel.

Parameters:

  • capacity (int) — the maximum number of slots (spaces for channel:put messages) that can be in use at once. The default is 0.

Returns

new channel object.

Return type

userdata. In the console output, it is serialized as channel: [number], where [number] is the return of [channel_object:count()](#channel_object-count).

channel_object

method put(message[, timeout])

Send a message using a channel. If the channel is full, channel:put() waits until there is a free slot in the channel.

  • message (lua-value) — what will be sent, usually a string or number or table

  • timeout (number) — maximum number of seconds to wait for a slot to become free. Default: infinity.

Returns

If timeout is specified, and there is no free slot in the channel for the duration of the timeout, then the return value is false. If the channel is closed, then the return value is false. Otherwise, the return value is true, indicating success.

Return type

boolean

close()

Close the channel. All waiters in the channel will stop waiting. All following channel:get() operations will return nil, and all following channel:put() operations will return false.

get([timeout])

Fetch and remove a message from a channel. If the channel is empty, channel:get() waits for a message.

  • timeout (number) — maximum number of seconds to wait for a message. Default: infinity.

Returns

If timeout is specified, and there is no message in the channel for the duration of the timeout, then the return value is nil. If the channel is closed, then the return value is nil. Otherwise, the return value is the message placed on the channel by channel:put().

Return type

usually string or number or table, as determined by channel:put``

is_empty()

Check whether the channel is empty (has no messages).

Returns

true if the channel is empty. Otherwise false.

Return type

boolean

count()

Find out how many messages are in the channel.

Returns

the number of messages.

Return type

number

is_full()

Check whether the channel is full.

Returns

true if the channel is full (the number of messages in the channel equals the number of slots so there is no room for a new message). Otherwise false.

Return type

boolean

has_readers()

Check whether readers are waiting for a message because they have issued channel:get() and the channel is empty.

Returns

true if readers are waiting. Otherwise false.

Return type

boolean

has_writers()

Check whether writers are waiting because they have issued channel:put() and the channel is full.

Returns

true if writers are waiting. Otherwise false.

Return type

boolean

is_closed()

Returns

true if the channel is already closed. Otherwise false.

Return type

boolean

Example

This example should give a rough idea of what some functions for fibers should look like. It's assumed that the functions would be referenced in fiber.create().

fiber = require('fiber')channel = fiber.channel(10)function consumer_fiber()    while true do        local task = channel:get()        ...    endendfunction consumer2_fiber()    while true do        – 10 seconds        local task = channel:get(10)        if task ~= nil then            ...        else            – timeout        end    endendfunction producer_fiber()    while true do        task = box.space...:select{...}        ...        if channel:is_empty() then            – channel is empty        end        if channel:is_full() then            – channel is full        end        ...        if channel:has_readers() then            – there are some fibers            – that are waiting for data        end        ...        if channel:has_writers() then            – there are some fibers            – that are waiting for readers        end        channel:put(task)    endendfunction producer2_fiber()    while true do        task = box.space...select{...}        – 10 seconds        if channel:put(task, 10) then            ...        else            – timeout        end    endend

Condition variables

Call fiber.cond() to create a named condition variable, which will be called 'cond' for examples in this section.

Call cond:wait() to make a fiber wait for a signal via a condition variable.

Call cond:signal() to send a signal to wake up a single fiber that has executed cond:wait().

Call cond:broadcast() to send a signal to all fibers that have executed cond:wait().

cond()

Create a new condition variable.

Returns

new condition variable.

Return type

Lua object

: cond_object

wait([timeout])

Make the current fiber go to sleep, waiting until another fiber invokes the signal() or broadcast() method on the cond object. The sleep causes an implicit fiber.yield().

Parameters:

  • timeout — number of seconds to wait, default = forever.

Returns

If timeout is provided, and a signal doesn't happen for the duration of the timeout, wait() returns false. If a signal or broadcast happens, wait() returns true.

Return type

boolean

signal()

Wake up a single fiber that has executed wait() for the same variable. Does not yield.

Return type

nil

broadcast()

Wake up all fibers that have executed wait() for the same variable. Does not yield.

Return type

nil

Example

Assume that a Tarantool instance is running and listening for connections on localhost port 3301. Assume that guest users have privileges to connect. We will use the tt utility to start two clients.

On terminal #1, say

$ tt connect localhost:3301tarantool> fiber = require('fiber')tarantool> cond = fiber.cond()tarantool> cond:wait()

The job will hang because cond:wait() -- without an optional timeout argument -- will go to sleep until the condition variable changes.

On terminal #2, say

$ tt connect localhost:3301tarantool> cond:signal()

Now look again at terminal #1. It will show that the waiting stopped, and the cond:wait() function returned true.

This example depended on the use of a global conditional variable with the arbitrary name cond. In real life, programmers would make sure to use different conditional variable names for different applications.