Skip to content

Repository files navigation

Wire

License Wally

A high-performance, signal and request library for Roblox. Wire provides lightweight alternatives to `BindableEvent` and `BindableFunction` with superior performance and a clean, functional API.

Features

  • Blazing Fast — Outperforms GoodSignal, SignalPlus, and FastSignal in benchmarks
  • O(1) Disconnect — Doubly-linked list architecture enables constant-time connection removal
  • Thread Pool Recycling — Efficient coroutine reuse for async operations
  • Parallel Luau Support — First-class support for parallel execution with connectParallel
  • Dual Paradigm — Both event-style signals and RPC-style requests
  • Type-Safe — Full Luau strict mode with exported types
  • Zero Dependencies — Pure Luau implementation
  • Memory-Efficient — Instead of creating a table & using metatables for every signal object, it simply creates an ID and only stores head & tail connections when needed

Installation

Wally

[dependencies]
Wire = "elentium/wire@0.0.4"

Manual

install the roblox-direct/Wire.rbxm and insert in studio

Quick Start

local Wire = require(path.to.Wire)

-- Create a signal
local PlayerDamaged = Wire.signal()

-- Connect a listener
local connection = Wire.connect(PlayerDamaged, function(player, damage)
    print(player.Name .. " took " .. damage .. " damage!")
end)

-- Fire the signal
Wire.fire(PlayerDamaged, player, 25)

-- Disconnect when done
connection:disconnect()

API Reference

Constructors

Wire.signal() -> number

Creates a new signal and returns its entity ID.

local MySignal = Wire.signal()

Wire.request(callback?) -> number

Creates a new request (similar to BindableFunction) and returns its entity ID.

local GetPlayerData = Wire.request(function(player)
    return playerDataStore[player]
end)

Signal Methods

Wire.connect(entityID, callback) -> WireConnection

Connects a callback to a signal. Returns a connection object.

local connection = Wire.connect(MySignal, function(...)
    print("Signal fired with:", ...)
end)

Wire.connectParallel(entityID, callback) -> WireConnection

Connects a callback that runs in parallel (for Parallel Luau).

Wire.connectParallel(HeavyComputation, function(data)
    -- This runs desynchronized from the main thread
    processData(data)
end)

Wire.once(entityID, callback) -> WireConnection

Connects a callback that automatically disconnects after the first fire.

Wire.once(GameStarted, function()
    print("Game has started!")
end)

Wire.onceParallel(entityID, callback) -> WireConnection

Combines once and connectParallel — runs once in parallel, then disconnects.

Wire.fire(entityID, ...) -> ()

Fires a signal synchronously. All callbacks execute sequentially in the current thread.

Wire.fire(MySignal, "arg1", "arg2", 123)

Recommended for non-yielding callbacks. Most performant option.

Wire.fireSafe(entityID, ...) -> ()

Fires a signal synchronously. All callbacks are wrapped in pcall and are executed sequentially in the current thread.

Wire.fire(MySignal, "arg1", "arg2", 123)

Recommended for non-yielding callbacks that can error and you do not want it to stop other connections.

Wire.fireAsync(entityID, ...) -> ()

Fires a signal asynchronously. Each callback runs in its own coroutine.

Wire.fireAsync(MySignal, data)

Use when callbacks may yield (e.g., contain task.wait, HTTP requests, etc.)

Wire.await(entityID) -> ...any

Yields the current thread until the signal fires, then returns the fired arguments.

local damage, attacker = Wire.await(PlayerDamaged)
print("Received damage:", damage, "from", attacker)

Wire.disconnectAll(entityID) -> ()

Disconnects all connections from a signal. Can also serve as a signal destructor.

Wire.disconnectAll(MySignal)

Request Methods

Wire.onInvoke(entityID, callback) -> ()

Sets or updates the callback for a request.

Wire.onInvoke(GetPlayerData, function(player)
    return database:GetAsync(player.UserId)
end)

Wire.invoke(entityID, ...) -> ...any

Invokes a request and returns the result.

local data = Wire.invoke(GetPlayerData, player)

Wire.destroyRequest(entityID) -> ()

Removes the request callback, freeing the reference.

Wire.destroyRequest(GetPlayerData)

Connection Object

connection:disconnect() -> ()

Disconnects the connection from its signal.

local connection = Wire.connect(MySignal, callback)
-- Later...
connection:disconnect()

Performance

Benchmarks run with 10 connections per signal:

Operation Wire GoodSignal SignalPlus FastSignal
Fire (100k iterations) 0.490s 0.552s 0.587s 0.677s
Disconnect (1k items) 0.00007s 0.0155s 0.00008s 0.00009s

Wire achieves the fastest fire times and the fastest disconnect times thanks to its doubly-linked list architecture (O(1) removal vs O(n) for array-based implementations).

Best Practices

Use fire over fireAsync when possible

fire is significantly faster because it avoids coroutine overhead. Only use fireAsync when your callbacks yield.

-- ✅ Good: Non-yielding callback with fire
Wire.connect(DamageDealt, function(amount)
    healthBar:Update(amount)
end)
Wire.fire(DamageDealt, 50)

-- ✅ Good: Yielding callback with fireAsync
Wire.connect(SaveData, function(player)
    dataStore:SetAsync(player.UserId, getData(player))
end)
Wire.fireAsync(SaveData, player)

Handle errors in callbacks when using fire

With fire, an error in any callback will halt execution. Wrap risky code in pcall:

Wire.connect(RiskySignal, function(data)
    local success, err = pcall(function()
        processUnsafeData(data)
    end)
    if not success then
        warn("Handler error:", err)
    end
end)

Clean up connections

Always disconnect connections when they're no longer needed to prevent memory leaks:

local connections = {}

function module:Init()
    table.insert(connections, Wire.connect(Signal1, handler1))
    table.insert(connections, Wire.connect(Signal2, handler2))
end

function module:Destroy()
    for _, conn in connections do
        conn:disconnect()
    end
    table.clear(connections)
end

License

Apache-2.0 — See LICENSE for details.

Links

About

No description, website, or topics provided.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages