#Signal Certifications & Class-Grader

1 messages Β· Page 3 of 1

stuck thorn
#

truly deferred is deferred

#

not just semi deferred

#

and I think best change is... if you want OG disconnect all then

#

Deferred disconnect nested connections + default disconnect current connections

#

oh no, I mightve realized a bug

#

calling the smae function twice would cause it to change to DISCONNECT_EVERYTHING

#

πŸ’”

scarlet pecan
stuck thorn
#

now it shouldn't happen

scarlet pecan
scarlet pecan
stuck thorn
#

guess now it's a waiting game for github

stuck thorn
stuck thorn
#

thats when you want it deferred

#

it firstly go "ok ima clean nested connection" and then "ok ima clean everything"

stuck thorn
#

hmmm, seems like im not using the entire potential of lastQueueClear, but ill that as is because I'd need extensive performance testing

rough rivet
#

oh now that's bullshit

#

fuck you roblox

stuck thorn
#

then you got everything in 1 iteration

#

Im gonna wager that option, but I should benchmark to see if it does make a difference

stuck thorn
stuck thorn
#

the ⁨disconnection awe⁩ update is here

proven yoke
#

this is %100 best signal unit test ever

stuck thorn
stuck thorn
scarlet pecan
#

Optimized connection insertion to the priority LinkedList πŸ‘

  • Removed the ⁨⁨⁨⁨⁨⁨⁨⁨⁨side⁩⁩⁩⁩⁩⁩⁩⁩⁩ variable & moved code so 1 less if-statement is used.
  • Added the ⁨⁨⁨⁨⁨⁨⁨⁨⁨usesPriority⁩⁩⁩⁩⁩⁩⁩⁩⁩ ⁨⁨⁨⁨⁨⁨⁨⁨⁨(nil | true)⁩⁩⁩⁩⁩⁩⁩⁩⁩ flag for each signal, to simply insert new connections to the priority head if only the DEFAULT_PRIORITY has been used without any further logic or LinkedList checks.
    ^ Most of the changes are in the ⁨⁨⁨⁨⁨putInPriority⁩⁩⁩⁩⁩ function
#

Before:

#

After:

#

^ Only affects ⁨⁨Connect⁩⁩ & ⁨⁨Once⁩⁩ benchmarks, ignore Fire_ benchmarks

stuck thorn
#

this shouldn't change "much", but it does remove useless mutations lol

scarlet pecan
# stuck thorn

Does this include the optimization I provided?
Gonna add it real quick

stuck thorn
#

No, I did this seperately

#

(because I haven't seen what you did)

#

but ill implement that my own way if you want

scarlet pecan
#

Already added (I just copy-pasted the ⁨⁨⁨putInPriority⁩⁩⁩ function I did & included the ⁨⁨⁨_usesPriority⁩⁩⁩ type)

stuck thorn
#

0.7 microseconds on manyyield, yikes...

scarlet pecan
stuck thorn
#

it should not

stuck thorn
#

let me know if it's good

stuck thorn
#

(still covers the edge case, just now more "clearly")

#

woah, can't believe we dedicated optimization updates now

rough rivet
#

yeeeeees yeeeees more more MORE!!!

stuck thorn
#

I mean speed can be gained from inlining stuff, but I doubt I want to ruin readability lol............

#

OH wait... INLINE fire functions....

stuck thorn
scarlet pecan
stuck thorn
#

I mean reduced overhead on that one

#

so I think it's OK now

#

^ ironically if it wasn't for priority connections then some things would've been faster

stuck thorn
#

@scarlet pecan so I guess it should be ok to update now

rough rivet
#

ping me when update, thanks

stuck thorn
#

I wasn't sure if MaddestCat did it, but he did

stuck thorn
rough rivet
#

i'd fix the variable shadowing if i were you

#

for example you use "type" a lot

#

see how type is blue

stuck thorn
#

I don't think you will ever see yourself using ⁨⁨type⁩⁩ in a signal inside of a method / function, only ⁨⁨typeof⁩⁩ 😭

rough rivet
#

yeah but either way

#

same with next

stuck thorn
#

meh, it works so it works

rough rivet
#

fair enough

stuck thorn
#

It's "hard" to avoid variable shadowing when you only want to convey the message (and not make it long) 😭

scarlet pecan
stuck thorn
#

thank you

stuck thorn
# stuck thorn (still covers the edge case, just now more "clearly")

shouldve probably said what the "edge case" couldve been, basically you change priority of current connection (which is deferred), then you force disconnect current connection, and if you call :DisconnectNestedConnections(), change priority mutation gets excluded from transfer table

#

but I fixed that by just... not excluding it from the transfer table

#

that was my nichΓ© problem

stuck thorn
#

Im guessing all is good? no issues with the signal?

scarlet pecan
# stuck thorn Im guessing all is good? no issues with the signal?

Haven't used it in a real-situation yet, I'm still developing my own tools before I continue my projects (working on a successor to Janitor for more versatility rn)
The Signal Certifications Grader and Behaviors Tests are speculative of nearly all real situations I would use a Signal in though, no issues about SomeSignal on my end πŸ‘

stuck thorn
#

πŸ˜”

#

guess I really do need use this in my TD project to see if it can be used normally

#

lol

#

hell yea this time ordering doesnt matter because I can just assign priorities

scarlet pecan
#

Built-in custom ordering will save me a lot of time

rough rivet
#

we need a #1017074018987290644 post on this...

scarlet pecan
rough rivet
stuck thorn
#

I wonder what it will be so "successor" about it, customizable cleanup keywords?

scarlet pecan
# stuck thorn I wonder what it will be so "successor" about it, customizable cleanup keywords?

Here's a demo if you would like to check it out, I've left most of the current documentation in the typing. Let me know if you have any questions, suggestions, or if anything is wrong. πŸ™

NOTE: IT'S NOT COMPLETE YET

To do tomorrow:

  • βœ… Fix :AssignToNewJanitor()'s bug
    • Also rename to :MoveToJanitor() to be more implicitly accurate
  • JanitorMeta:LinkToSignal(methodName: MethodName, signal: Signal, persist: boolean)
    • Links a specific method to the provided signal, allows for multiple signals & will disconnect all non-persisting connections upon cleaning up.
    • MethodName is just the current method-strings of Janitor, most importantly being CleanupAll or RemoveAll.
  • Add more TypeCleanupMethods presets
    • MadJanitor is already compatible with ANY input value for as long as it already has a preset or you can customize its objectConfigs, presets are just for convenience (automatic cleanupMethod detection).
    • Promise preset
    • Think of some more presets later
  • Misc. methods (easy but low-priority)
    • JanitorMeta:Destroy()
    • ObjectMeta:SetForcedType()
  • Actually do better type generics for value for the sake of autofill... this is gonna be fun... πŸ’€
  • Thoroughly test all methods in every niche situation I can think of
    • It should already work for the most part after doing a few rough tests, but there may still be bugs.
    • Also be on the look out for documentation inconsistencies, I had to revise a huge chunk of it twice so some parts I've forgotten to update may be outdated. πŸ’€
  • Benchmark & work on optimizations. Will do this last, only after I've confirmed everything to be working.
    Documentation here:
scarlet pecan
scarlet pecan
#

Here's some example code if you want to get a feel of how MadJanitor could be used (this doesn't include everything)

scarlet pecan
#

There's a bug with [object]:AssignToNewJanitor(), working on it tomorrow

stuck thorn
#

Interesting, but I think i'd stick to me being the janitor

rough rivet
stuck thorn
#

Wild that you actually updated it

#

😭

scarlet pecan
# stuck thorn Wild that you actually updated it

I was curious lol, but I now consider it somewhat useless though with how little the differences in speed actually matter unless you frequently use 10k+ connections.
If using less than that? I heavily prefer utility (SomeSignal) over human-imperceptible speed.

stuck thorn
#

cant believe it that my signal almost can catch fastsignal

#

πŸ˜”

#

though I should probably refine SomeSignal function comments and then possibly make a forum post (without github link, it takes like 5 business days for a response)

rough rivet
#
#

get a move on ladies

#

also what's the point of making it compatible with the old type solver

#

fuck that

stuck thorn
stuck thorn
rough rivet
#

i think this would be nice in somesignal too

stuck thorn
#

this would throw old type solver support, cough cough

rough rivet
#

NOBODY CARES ABOUT THE OLD TYPE SOLVER!!

#

RAH!!!!

stuck thorn
#

ill consider that once new solver is stable enough to migrate from old one

stuck thorn
#

it DOESNT WORK ON NEW SOLVER BECAUSE FUCK YOU!!!!!!

rough rivet
#

JUST USE BLINK

#

IT'S GETTING A REWRITE

stuck thorn
#

BUT I DONT NEED BLINK...

#

I NEED MY FRIGGIN PACKETS YO

scarlet pecan
rough rivet
stuck thorn
#

My point stands, ill wait until new solver is stable enough

#

because it was half of a excuse to release in a ass state

#

πŸ’”

rough rivet
#

i understand sir

#

it's okay i still love you

rough rivet
#

we need ALL the signals on it

stuck thorn
#

okay, insert ass forum post thing

#

(text isn't centered, to show that it's QUALITY)

stuck thorn
#

because this doesn't return object, just data

#

(data orientated design)

scarlet pecan
stuck thorn
#

you just murdered the entire "overhead" for it not being OOP anymore

stuck thorn
#

apparently I did that too, but Sinek didn't like the idea

#

(I wonder why...)

rough rivet
#

oh me oh my...

stuck thorn
#

NamedSignal is just Zignal + SignalPlus hybrid in a dressed hat ❀️

scarlet pecan
stuck thorn
rough rivet
#

wire can do parallel luau aswell...

scarlet pecan
# stuck thorn gotta require wire in every script/module which uses wireID

You could also store signals in a module with a key 😭

local SignalStorageMD = {}

local SignalArray = {}
local SignalDictionary = {}

SignalStorageMD.getSignal = function(signalId: any?)
  return SignalDictionary[signalId] or SignalArray[signalId]
end

SignalStorageMD.addSignal = function(signal: Signal, signalId: any?)
  if signalId then
    SignalDictionary[signalId] = signal
  else
    table.insert(SignalArray, signal)
    signalId = #SignalArray
  end
  return signal, signalId
end

return SignalStorageMD
rough rivet
#

my ass might have to switch to wire guys...

scarlet pecan
stuck thorn
#

sharedtable signal

#

TRUE PARALLEL βœ…

rough rivet
scarlet pecan
#

wait no my ass is dyslexic

#

it IS true parallel

patent ore
#

Wire is peak ? πŸ€”

scarlet pecan
stuck thorn
#

abusing docstring tags

stuck thorn
#

Okay refreshed SomeSignal function comments + removed that 1 misleading comment line from CancelAllMutations

stuck thorn
stuck thorn
scarlet pecan
stuck thorn
#

Which is to say

#

I leave in the module the version and then on creatoe store you got some like "V2.2.7"

scarlet pecan
#

ye exactly πŸ™
^ Or maybe just the module because people can just open up its code anytime from the creator store page

stuck thorn
#

Hm okay

stuck thorn
#

lul

stuck thorn
#

some x.4.x because it went through 4 "considerable" changes and then ehh... x.x.1 because function comment changes

#

V2.4.1 it is den

#

@scarlet pecan so this good?

scarlet pecan
stuck thorn
#

now the hardest part will be writing the forum post lol........

#

or I could just... put that off for late-

stuck thorn
#

because I dunno what i'd write that makes it stand out

#

that it passes all the tests your signal certification tests, lol?

scarlet pecan
# stuck thorn that it passes all the tests your signal certification tests, lol?

It might be best to emphasize that developers will have true complete control of connection-dispatch timing while remaining synchronous to Fire unlike ANY OTHER Signal/BindableEvent, and also explain the extra features that your signal comes with (basically what my guide did).
Also provide a few code-examples showcasing what it would look like using it, to visually help the people who may be confused

#

I can get started on the SomeSignal explanation & tutorial video on Monday if you want to use that instead

stuck thorn
#

πŸ€‘

#

That might give me a idea on how to write that now

#

but it'd be mostly about it's behavior compared to basic BindableEvent/Signal

stuck thorn
#

so to explain the whole deferred/immediate behavior, :Fire() yielding until it's done (synchronous)

twilit fern
stuck thorn
scarlet pecan
# twilit fern defered and nondefered fire support?

My guide explains part of it in detail:
https://devforum.roblox.com/t/signal-certifications-classes-guide/4263792/2?u=gohanducis

Connection mutations are optionally deferred in SomeSignal until after all synchronous connections are ran is what it means, all connections are ran immediately from start to finish by the time :Fire() returns (synchronous) for as long as the connections themselves don't become asynchronous (using a yield).

Example of synchronicity & asynchronicity:

local signal = SomeSignal.new()

local cn1 = signal:Connect(function()
  -- Starts off as synchronous
  print("wsg.")
end)

local cn2 = signal:Connect(function()
  -- Starts off as synchronous
  print("hi!")

  -- Mutation deferral example
  cn1:Disconnect() -- Mutation, this is deferred by default (until after all connections are ran, before :Fire() returns)
  print(cn1.Connected) -- true
  cn1:Disconnect("immediate") -- Mutation, this is forcefully immediate
  print(cn1.Connected) -- false

  -- Becomes asynchronous
  task.wait(2)
  print("hello!"
end)

-- ALL connections that 
signal:Fire() -- "wsg.", "hi!"
print("bruh.") -- "bruh."
-- 2 seconds later...
-- "hello!"

--[[
Output:
"wsg."
"hi!"
"bruh."
"hello!"
]]

#

^ The Snapshot Certification should clear this up a bit

stuck thorn
#

I only now realize that it's easier to do than explain lmao πŸ’”

twilit fern
#

i mean i personally dont have a reason to use task.spawn instead of defered but i can see some cases where ud need that

#

i also think doing

func() task.wait() end 

to defer is worse than (not sure jus from memory of reading it somewhere)

task.defer()
scarlet pecan
# twilit fern no what i meant was can u do :FireDefered() and Fire() where one uses task.spawn...

task.defer forces all connections to be asynchronous, which isn't good if you expect logic like this:

local count = 0

signal:Connect(function() -- Using task.defer on this will defer this function to the end of the current CPU cycle.
  count += 1
end)

signal:Fire()
print(count) -- 0, the connection wasn't ran before :Fire() returned which makes it asynchronous/annoying to work with if not intentional.
task.wait() -- Forces to wait 1 frame (at least 1 or millions of cycles)
print(count) -- 1
twilit fern
#

i was just wondering if this module supported 2 types of firing

scarlet pecan
#

Similar to why most signals don't have parallel connections (also easy to optionally do)

cn = signal:Connect(function()
  task.desynchronize
  ...
  task.synchronize
end)
twilit fern
#

also is snapshot certification something that u want

#

idk if this is standard practice but this is something i usually do

#

if some state or condition isnt met i expect it to halt right away at the very tipy top and return

scarlet pecan
# twilit fern also is snapshot certification something that u want

100%, it solves the primary issue in with mutations being forced to depend on connection-ordering.
Example with other signals:

local cn1, cn2
cn1 = signal:Connect(function()
  cn2:Disconnect()
end)
cn2 = signal:Connect(function()
  print("run?") -- This will never run because cn1 disconnected cn2.
end)

signal:Fire()

^ SomeSignal makes this optional without extra custom code on the developer's end.

-- Example with deferred mutations
local cn1, cn2
cn1 = signal:Connect(function()
  cn2:Disconnect()
end)
cn2 = signal:Connect(function()
  print("run!")
end)
signal:Fire() -- "run!"

-- Example with immediate mutations
local cn1, cn2
cn1 = signal:Connect(function()
  cn2:Disconnect("immediate")
end)
cn2 = signal:Connect(function()
  print("run!")
end)
signal:Fire() -- cn2 doesn't run.

--[[
Deferred mutations with existing connections are the default because of this logic:
"If I :Fire() this signal, I expect all connections to run no matter what unless I specify otherwise."
]]
twilit fern
#

wait sorry yes ure right

#

this isnt even nested i read that wrong

scarlet pecan
#

Nested connections run in the next Fire using SomeSignal (under the logic that only the existing connections upon :Fire() will run)
SomeSignal example:

signal:Connect(function()
  local nestedConnection = signal:Connect(function(fireId: number)
    print("FireId: " .. fireId)
  end)
  signal:Fire(2) -- "FireId 2", reentrant Fires will wait for all connections to run & mutations to be processed before starting, these will also finish before the "parent" :Fire() returns.
  signal:Fire(3) -- "FireId 3", consecutive reentrant Fires are also supported
end)
signal:Fire(1)
print("--------") -- Proof that nested/reentrant Fires are also synchronous
signal:Fire(4) -- "FireId 4"
--[[
OUTPUT:
"FireId 2"
"FireId 3"
"--------"
"FireId 4"
]]
#

@twilit fern Here's nearly every usage-example possible with SomeSignal (including extra features) if you're interested:

twilit fern
#

ye im interested ill take a look tmrw

#

nice work bro

#

clean clean

scarlet pecan
#

Most of it is @stuck thorn's work, I only provided the initial guide & assisted with logic + a few bug fixes πŸ’ͺ

stuck thorn
#

it does make you crazy though

#

Although it did make the previous & this month special

stuck thorn
#

wildest update of them all... 2.4.1.1

  • fixed one of the comments line position (its for the devs who want to learn from the code), I was drunk a bit
outer summit
#

The creator acknowledges that it sucks so much it needs a complete remake. πŸ€·β€β™‚οΈ

rough rivet
outer summit
rough rivet
#

I'm so proud of blink

#

that's my boy πŸ₯Ή

outer summit
#

How dare you assume its gender in 2026!?

stuck thorn
#

How did this turn into network library beef

rough rivet
rough rivet
#

i'm sorry blink

#

i've failed you as a parent

#

you're still the best networking library there is though

#

😌

stuck thorn
#

Well then, SomeSignal is not/it

stuck thorn
#

i got lost a bit

stuck thorn
#

@scarlet pecan are you gonna troll the next class 3 signal guy by adding "multi-signal behavior" certification?

#

πŸ₯€

stuck thorn
scarlet pecan
stuck thorn
#

GOOD GRIEF LOL

stuck thorn
stuck thorn
scarlet pecan
stuck thorn
#

Literally rigged battle from the start πŸ’”

stuck thorn
#

@scarlet pecan Also I think I know what NamedSignal owner talking about

#

Because its current is behavior equivalent of V1 of SomeSignal, connecting/disconnecting while signal is firing yields the thread

scarlet pecan
#

Added πŸ‘
Is it right?

stuck thorn
#

Should be right

#

Just that this does it in reentrancy levels

#

you get reentrancy levels from :Fire()

stuck thorn
stuck thorn
#

Hmmm, I left oversight in SomeSignal somewhere

#

^ this was the oversight

#

small fix later :

#

the pin pointed issue was that I checked if state is nil, while in actuality I should have not, as above if statement did block it from transfering over + current connections are disconnected before this check

#

This marks the 2.4.2.2 update, to indicate what changes were made, I will now give short summary on creator store

stuck thorn
rough rivet
#

MMMMMMMMMM

stuck thorn
#

@scarlet pecan I kinda find it weird

#

OHHH IM STUPID LOL

#

😭

#

I forgot that :Fire() while signal is firing yields the thread

scarlet pecan
#

Going full circle with this 😈

scarlet pecan
scarlet pecan
stuck thorn
#

h-hell naw!! πŸ—£οΈ

#

we all truly know the remedy for this issue

#

task.spawn(Signal.Fire, Signal, ...)

#

also im making a post about this, because I doubt it fits to comment every change here lmao

scarlet pecan
stuck thorn
#

No dev forum yet, bwomp.

stuck thorn
#

@scarlet pecan I think I got the craziest fix for tis...

#

if signal firing then task spawn a new thread <- althought it'd make fires not synchronous anymore

#

so ehhh, it'll be the dev job to decide if to yield or not

stuck thorn
#

I like how majority of the features are just "do it yourself"

scarlet pecan
#

utility versatility at its finest πŸ—£οΈ πŸ”₯

proven yoke
#

I have zignal that is converted from oop

#

its so easy to convert really just consumes very little extra memory

#

but it is worth it

stuck thorn
#

Ironically if it wasnt for yielding functions, signal fire could've been WAY faster

stuck thorn
#

(Connection object doesnt use __index metamethod lmao)

proven yoke
#

@scarlet pecan out there exposing bad signal behavior keep up bro

#

Ive had my fair share on fast signal

#

Bc there were no unit tests showing how bad it is

#

My legacy code literally had to be trashed bc of that

#

W

stuck thorn
#

W, this paid off lmao

scarlet pecan
#

Gonna update the Signal Grader today, upcoming features:

  • βœ… Support for signals that internally don't use threads at all for Connect & Once
    • tbh, I think it's a VERY good idea to optionally (not default Fire & certainly not the only option) have a Fire without asynchronicity safety. Because it blows BindableEvents right out of the water in speed for the Fire_One and Fire_Many tests specifically (NOT Fire_OneYield & Fire_ManyYield).
  • βœ… Tests for multi-signal usage
  • βœ… Tests for consecutive reentrant Fires (proven edge-case of a signal's internal design)
  • βœ… PCall test (to ensure Fires won't interrupt/break on a specific connection with an error)
stuck thorn
#

Is this gonna kill NamedSignal

scarlet pecan
stuck thorn
proven yoke
#

it will break if any of the subsequent functions errored

#

and wont run other stuff

#

1 bug leading to many bugs

stuck thorn
proven yoke
#

it's so hard to predict that

stuck thorn
#

Lion does not concern himself with error handling and codes with divine intellect

proven yoke
#

imagine CharacterAdded failing because somehow Insert service fails

stuck thorn
#

So we asking for promise execution

proven yoke
stuck thorn
#

Also what can fail with insert service

stuck thorn
#

I thought it was well known

#

Rahhhhhh

#

Which is still to say... Programmers duty

proven yoke
#

even after then

#

in live games

#

there might be stuff you missed

#

you don't want the game to just shit itself

#

if there's any errors

stuck thorn
#

Yeah we have a tool for that: promises

proven yoke
#

unironically

#

Ive seen this

#

deadass

stuck thorn
#

Wrapping everything in pcall ahh

#

πŸ™

proven yoke
#

pcall ing everything

stuck thorn
#

You can't ever be sure

#

Like I'm not dead-ass about it, TDS has that issue

#

It'll be loading controllers and then it stops because it got hit by a error

#

Good Lord LOL

#

Tis why you see signals task spawn stuff

stuck thorn
#

So that's errors beyond control for ya

scarlet pecan
proven yoke
stuck thorn
scarlet pecan
# proven yoke it should be a seperate category

I'll still have it as a part of the Scheduler certification, because the purpose I've given the cert is to guarantee basic functionality which includes being able to correctly execute all connections without weird bugs or interruptions, the latter I feel should account for pcalls that prevent Fires from breaking on specific connections that have errors

stuck thorn
#

Rest in peace

scarlet pecan
#

jk, here it is:

CHANGELOG

  • Scheduler Certification Changes
    • New test: AsyncErrorCatch, if signals that don't use threads for Connect & Once connections use pcall or xpcall instead for safe asynchronous error catching.
    • New test: ConsecutiveReentrancy, if a signal can do reentrant Fire in the same Fire layer, as well as reentrant Fire in multiple reentrant layers.
    • New test: MultiSignalCNs, tests if created connections are bound strictly to their signal in creation & to Fire.
    • New test: MultiSignalNested, an expansion of the previous test but for nested connections. Also tests if one signal can Fire other signals within its connections (nested but not reentrant Fire).
    • New test: MultiSignalDisconnectAll, if DisconnectAll only affects the signal it's used on.
  • Misc Changes
    • Now supports signals that internally don't use threads at all for Connect & Once within the primary :Fire() method, which also reflects the speed benefits in the Speed Certification's Fire_One and Fire_Many benchmarks.
#

CuteSignal failed the AsyncErrorCatch & ConsecutiveReentrancy tests

stuck thorn
#

really cooked that queue addition

scarlet pecan
#

Hold on I forgot to remove connection-ordering dependency for ConsecutiveReentrancy

#

Publishing to the devforum now

stuck thorn
#

Is this fire

scarlet pecan
# stuck thorn Is this fire

Indeed, 1 signal has been bumped down to Class 0 so far thanks to the new tests, FastSignal (I'm still retesting all signals)

#

DProSignal's Wait_Safety randomly broke on its own though

stuck thorn
#

I don't think ill change much, other than pointing out signal with bugs

scarlet pecan
stuck thorn
#

1/2 billion chance that a stray atom hit your pc and it changed code of DProSignal

scarlet pecan
#

nvm FastSignal is actually fine
Changes:

  • Fixed the Baseline insertion algorithm for MultiSignalCNs & MultiSignalNested
  • Fixed support for asynchronous Fires in the new tests (FastSignal confirmed it)
#

Sending the fixed grader in a sec after I test other signals

scarlet pecan
#

Updating the devforum fr this time (retesting all signals)

stuck thorn
#

I was expecting bloodshed, but this good news atleast

scarlet pecan
#

okay final hotfix FR* this time trust, it's now more obvious if a value doesn't pass through in MultiSignalCNs & MultiSignalNested (so they're not mistaken for a false negative)

scarlet pecan
#

Updated the devforum πŸ‘

stuck thorn
#

😭

#

ironically would be funny if those "checks" you do before break it

scarlet pecan
#

Imagine πŸ’€

#

It's thankfully all good now though lol

#

Retested CuteSignal, it's just missing pcall/xpcalls in its Connect & Once connections and then it'll be Class 1
Check out the Fire_One and Fire_Many speeds though, that's 3-4 times faster than other fastest signals that wrap connections in threads only (granted, they aren't wrapped in a pcall/xpcall yet) πŸ”₯

stuck thorn
#

isn't wrapped in task.spawn

#

absolutely blitzes fire one yield and many yield

scarlet pecan
#

Who could have known such a revelation! πŸ₯€

scarlet pecan
# stuck thorn absolutely blitzes fire one yield and many yield

Would it be possible to add optional SyncFire methods to SomeSignal so devs that don't use yields at all in their connections could take advantage of the speed? (Practically useless in nearly all cases except heavy simulation workloads)

signal:Fire()
signal:PriorityFire()

signal:SyncFire()
signal:SyncPriorityFire()
stuck thorn
#

I did wager that option, but I haven't seen any performance difference

#

linked list is making the iteration FAT

scarlet pecan
#

task.spawn takes up about 0.3μs in benchmarks & is the reason why most signals aren't faster then BindableEvents in Fire speeds (on my device*) 😭

stuck thorn
#

in my computer 1 connection makes this 1 small thing take ~10ΞΌs

#

(also how'd it work, fires do yield so you'd need to be wary...)

scarlet pecan
stuck thorn
#

πŸ”₯

#

although, I think it'd be nice to warn the user atleast if one thing fails in a pcall

#

HELL YEA LOL

scarlet pecan
# stuck thorn xpcall which just redirects to warn

xpcall returns a result from the 1st function if there's no error, otherwise returns from the 2nd function

-- Example 1
local success, result = xpcall(function()
    local sum = "fifty" + 2
    return sum
end, debug.traceback)

if success then
    print(result)
else
    error(result) -- Error + traceback
end

-- Example 2
local success, result = xpcall(function()
    local sum = 50 + 2
    return sum
end, debug.traceback)

if success then
    print(result) -- 52
else
    error(result)
end

-- Example 3
local success, result = xpcall(function()
    local sum = "fifty" + 2
    return sum
end, function() return "Do you have less braincells than the NUMBER you tried adding to the WORD STRING...?" end)

if success then
    print(result)
else
    warn(result) -- "Do you have less braincells than the NUMBER you tried adding to the WORD STRING...?"
end
stuck thorn
#

IM RUNNING 10K VOID CONNECTIONS WITH SYNC FIRE

#

πŸ€‘

#

like it only expects boolean while what it should return is boolean and R...

scarlet pecan
#

I think my brain isn't braining rn, my apologies πŸ™

stuck thorn
#

basically to show xpcall (the err function being the warn) in action

#

@scarlet pecan give it a go

#

(I just copy and pasted the fire functions)

#

actually I forgot 1 thing

#

dang

#

also, this doesn't make much different if you have 1 connection, it pays off when you get 100+ connections

#

while most pleasing is when you get 10k connections, then it runs at 60 fps for me

#

actually damn, I realized this bumps the ceiling a lot higher (50k connections and still 60 fps, although all frame budget went to iterating allat)

#

@scarlet pecan

#

after that it stopped, now I know why

#

what a screaming beast

scarlet pecan
#

Before:

#

Oh I gotta reword the errors (it did pass the AsyncErrorCatch test dw)

#

It froze on theConsecutiveReentrancy though

stuck thorn
#

so you'd need to conviniently wrap that in task.spawn... (trust me bro, this will be the SomeSignal META)

scarlet pecan
#

RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGH

stuck thorn
#

is it okay, or should I change the behavior?

scarlet pecan
stuck thorn
#

mein gott...

#

(this will require entire removal of enqueue from the start, so uhhh... have fun!!!!)

#

but then the basic fire will get in the way lmao

scarlet pecan
#

oh yeah there's that too, multi-Fire edge cases...

stuck thorn
scarlet pecan
scarlet pecan
#

HEHEHEHEHEHE

#

πŸ—£οΈ πŸ”₯
nvm I'm stupid, I forgot to pass the signal πŸ€¦β€β™‚οΈ

stuck thorn
#

I got a better idea

scarlet pecan
scarlet pecan
stuck thorn
#

I think I made it mad

#

atleast it doesn't yield the thread now

#

it just throws C stack overflows

scarlet pecan
#

Getting somewhere πŸ”₯

stuck thorn
#

now it passes, but it fails synchronous

#

ah okay because I don't wait anymore...

scarlet pecan
stuck thorn
#

that's why

scarlet pecan
#

oh?

stuck thorn
#

like I don't wait for fire in syncfire, it just goes

#

that's why you get 0 and then 2

#

because it's async

#

if I say that right...

scarlet pecan
#

I get it, but I don't understand much on why the Handler_Result connection wouldn't run

#

Is it being overwritten or skipped because of the asynchronous reentrant fires?

stuck thorn
#

other than that, it works

scarlet pecan
#

oh neat πŸ”₯

stuck thorn
#

we just assign a different thread to enqueue to the fire queue

#

lmao

scarlet pecan
#

recursive function thread deluxe πŸ˜‹

#

Good stuff as long as it works lol

stuck thorn
#

can't believe it's V2.5

scarlet pecan
#

W Speed πŸ”₯

#

But...

stuck thorn
#

I am not fixing that (You void reliability with SyncFire)

#

actually fixed it, just removed that it respects if signal is firing

#

just that using Fire inside SyncFire will yield SyncFire thread

#

you is welcome

scarlet pecan
stuck thorn
#

I wanted SyncFire to respect signal firing, but that's like asking unreliableremote to be reliable

#

it won't be πŸ’”

scarlet pecan
#

I have the right version right-?

#

Only modification I did to test SyncFire in the Grader (if that broke anything)

stuck thorn
#

OH WAIT LMAO

#

I forgot to change Fire to SyncFire

stuck thorn
#

okay I get it now, syncfire would even need to ignore mutation(s)

scarlet pecan
#

oh right to make them immediate only

stuck thorn
#

oh hell nah, that changepriority gonna fuck up so syncpriority fire so much LOL

scarlet pecan
#

Indeed πŸ˜”

#

I guess that's a given with immediate-only synchronicity lol, developers are on their on at that point if they choose to use SyncPriorityFire despite that

stuck thorn
#

yeah okay, it ate crap in snapshot behavior, as expected of course

#

ironically, it does make this very fast

#

@scarlet pecan so now it should be OK

#

gah damn I realized what blunder can happened with you disconnect the last connection

scarlet pecan
#

Some mutations should still safely be kept even with immediate synchronous connections πŸ™

stuck thorn
#

it'll still keep going lmao

scarlet pecan
#

How wonderful 😊

stuck thorn
#

like im not joking this is where going from newest to oldest would benefit πŸ€‘

#

actually that pisses me off ngl

scarlet pecan
#

It can be solved if you reimplement the mutation queue

#

oh wait then that loops right back to the reentrancy problem

#

What if...

#

You process mutations at the START of the Fire only if it's a reentrant Fire?

#

And then if it's the main/original Fire it does it at the end instead

stuck thorn
scarlet pecan
#

oh wait that still doesn't solve it, it would only be a partial solution because it won't be able to account for "future mutations" of the reentrant Fire's Parent Fire... (referring to my msg above)

scarlet pecan
stuck thorn
scarlet pecan
#

(might still be acceptable)

stuck thorn
#

patched that out, MUAHAHAHAHAHA

stuck thorn
#

I hope this would be the last, cause I want to sleep and maybe tomorrow release that as a "update"

#

also I shouldn't be worrying about mutations (or the snapshot behavior) on SyncFire, that's quite literlaly if you want it RIGHT NOW and don't want to wait for mutations

scarlet pecan
#

But yeah I agree honestly

stuck thorn
scarlet pecan
# stuck thorn I mean I could probably make some changes to make this work and pass snapshot be...

I lowkey think this genuinely might be impossible to solve because of logic timing, resulting in a catch-22 loop that urges reentrant Fires to become deferred again
The best that could be done is processing mutations at the start of the reentrant Fire, and remaining mutations of the og Fire at the end (after all connections are ran). This isn't a 100% solution because the reentrant Fire mutation-processing won't account for future deferred mutations of the og Fire...

#

All roads lead back to queues...

stuck thorn
#

yeah, so ill keep as is

#

let it be ugly, but tasteful

#

so I guess it should be okay to release

#

but how would I demostrate how to be used

#

actually I don't have to, that can just be a update log with mention of said ting...

scarlet pecan
# stuck thorn but how would I demostrate how to be used

2 use-cases I can think of (if you still wanted to):

  • Very fast data change receives & process-triggering for individual objects on a massive scale, think of NPCs (1k+ of them each with their own value-changed event) or projectiles (10k+ at once in one event)
    • This HEAVILY benefits from not needing to create threads (they're the most expensive part of Firing) so there's a LOT more CPU processing room.
  • Could be used to trigger something in stages (one connection per stage of the process), think of an ability usage in battlegrounds-related games. But I feel like this falls into the boilerplate category, this can easily be achieved using a single connection.
stuck thorn
#

we all know this is not beating arrays

#
  • famous words by Yarik
scarlet pecan
#

I hate he would be right if it wasn't for the fact that arrays are a bit difficult to deal with if you attempted to convert SomeSignal to an array-based signal 😭

stuck thorn
#

I think it's common sense ngl

#

For bunch of NPCs, nuthin beats arrays

scarlet pecan
#

oh you meant that, yeah lol

stuck thorn
#

I can't believe I ripped off CuteSignal and got away with it

#

πŸ—£οΈ

scarlet pecan
#

"I wish I was high on pot nuse" ahh signal 😭

stuck thorn
#

SomeSignal is a abomination due to 2 additonal fire methods

#

Although it's probably best to transfer this to #1471192412696088688

scarlet pecan
#

Sounds good

stuck thorn
#

Even if I'm going to sleep in a bit

scarlet pecan
stuck thorn
stuck thorn
#

source: trust me bro

stuck thorn
proven yoke
stuck thorn
#

it'll be fast but break down after 1 error

#

🌹

#

the gambit fire

proven yoke
#

this aint subjective gng πŸ˜”

stuck thorn
#

who needs code standards

#

it just needs to... WORK!!!

proven yoke
#

who needs CI tests

#

who needs safety

stuck thorn
#

who needs unit tests, I say it'll pass flawlessly by my judgement

proven yoke
#

they never do verifying

#

never test special cases

#

every code to their own beauty 🌹

stuck thorn
#

I curse my signals SyncFire just because you need to write spicy code for it (it's for oldest -> newest fire order)

#

🌹

#

@proven yoke beauty of it's own

#

actually dang, I could've used return for this COUGH COUGH

#

tank you DrSienk for pointing out my coding beauty

stuck thorn
#

PatientSand

proven yoke
stuck thorn
#

SinukudePh

proven yoke
stuck thorn
#

😭

atomic furnace
rough rivet
#

@scarlet pecan wait for the signal tests i assume you update each signal and check if they have --!optimize 2 beforehand right?

scarlet pecan
proven yoke
stuck thorn
scarlet pecan
#

CHANGELOG

  • Misc Changes
    • The grader no longer gets stuck on a few indefinite yield cases (regarding Wait_Safety & Wait_Chained tests) and C stack overflow errors (ConsecutiveReentrancy test).
      • Meaning? Extremely bugged signals such as ZeroSignal can now run the Signal Grader to completion.
stuck thorn
#

I guess it wasn't lying, it is indeed SPEED (lie)

stuck thorn
#

it ate all the speed

scarlet pecan
#

The creator of ZeroSignal strikes again with a new signal... But this time it's ACTUALLY GOOD πŸ—£οΈπŸ”₯πŸ”₯πŸ”₯
https://devforum.roblox.com/t/flow-signal-advanced-signal-library/4413930

stuck thorn
atomic furnace
atomic furnace
#

Also, I didn't get their NULL thing
I benchmarked it and the difference is negligible and requires huge amount of iterations in order to see it
Just an another micro optimization...

#

Also, the author's and Yarik's nicknames are both russian so I guess they're friends

#

Or it's just a coincidence

stuck thorn
#

If you want null thing then you should've made a empty buffer (though doubt that'd change anything)

atomic furnace
#

And, perhaps, SOA

stuck thorn
#

I don't know about SOA, but no metatable does make a difference

atomic furnace
#

Kind of ECS

#

But simpler

stuck thorn
#

😭

atomic furnace
stuck thorn
#

I just don't know if it does make a difference

atomic furnace
stuck thorn
atomic furnace
stuck thorn
#

I used that for SomeSignal mutation queue, even if it doesn't add much

#

Just 1 less thing to iterate through

stuck thorn
#

That reward is going to roblox itself lmao, everything has rbxscriptsignal

rough rivet
#

i like going to the somesignal devforum post or the signal certifications one and just reading the comments

#

this much beef over signal modules 😭

scarlet pecan
stuck thorn
#

"Yay another signal module which nobody will use!"

scarlet pecan
# stuck thorn "Yay another signal module which nobody will use!"
#

testing it rn

stuck thorn
stuck thorn
#

LOL 😭

scarlet pecan
# scarlet pecan ...

It didn't even occur to me that it was possible to pass in Connect_Safety but NOT general Connect functionality...

stuck thorn
#

another signal fell victim to signal certifications

stuck thorn
scarlet pecan
#

Makes sense

stuck thorn
#

had it been 2, it'd probably fail

stuck thorn
#

This guy knows how to optimize, unlike yarik

rough rivet
#

2014 from stravant

scarlet pecan
rough rivet
#

please test it i want to know how bad / good it is

#

let's see if it stands the test of time 😈

stuck thorn
rough rivet
#

stravant made goodsignal too so

stuck thorn
scarlet pecan
rough rivet
stuck thorn
#

If you check the code, then it's just a wrapper for BindableEvent

rough rivet
#

can't you just pass in empty functions for once and disconnectall

#

or check if those methods even exist in the first place 😭

scarlet pecan
rough rivet
#
#

pretty sure that's why it's just a bindable wrapper

stuck thorn
#

wow im failing the stravants signal test, my signal SUCKS... I should return to GOODSIGNAL.....

rough rivet
#

what the freak

scarlet pecan
scarlet pecan
rough rivet
proven yoke
scarlet pecan
stuck thorn
#

if it wasn't for GoodSignal, there would be no Zignal

#

☹️

proven yoke
#

true Ig

#

still zignal is the king

stuck thorn
#

because that would be wild

scarlet pecan
rough rivet
#

i wonder, is it even possible to not be speed certified?

scarlet pecan
scarlet pecan
stuck thorn
#

Guess SomeSignal doing war crimes (it sometimes failing at many_yield)

stuck thorn
#

guess tas teh cost of mutation queue (because roblox no give a optimized queue)

#

actually that does make me wonder, had I proposed a fix for signal+, it'd actually not be in class 0 lmao 😭

rough rivet
#

destroying reputations 1 while loop at a time

#

😈

stuck thorn
#

LOL NVM (I done screwed something up)

#

awesome

#

after the ""fix""

#

actually lol, if it was changed a bit more then it climbs to class 2

scarlet pecan
scarlet pecan
stuck thorn
#

Didn't bother benchmarking

stuck thorn
scarlet pecan
#

Before:

#

After:

#

2 class bump and no changes in speed πŸ”₯

stuck thorn
#

this debt comes at the cost of needing to scroll to find the end if something happens

#

truly

rough rivet
#

this is from ffrostfall

#

i'd test it

#

also this link is invalid

#

i get a 404 error

scarlet pecan
scarlet pecan
stuck thorn
proven yoke
#

that was the issue

#

literally

#

can you test the signal under the Packet

#

Im like %99 sure I had a weird behavior with it

proven yoke
#

this means you won

scarlet pecan
scarlet pecan
#

Poor dude got cyber-bullied to the point a mod had to remove it 😭

stuck thorn
#

☹️

proven yoke
#

But vaguely I remember it was due to :Wait

stuck thorn
proven yoke
#

I will never know what happened back then

stuck thorn
#

Actually wait...

#

lol fair, because it does task.defer

#

(I chucked my own DisconnectAll just so it no cry about it

#

this is technically snapshot certified, but at what cost...

proven yoke
#

I dont get it

stuck thorn
#

so obviously if you fire 2 fires in quick succession, that :Wait() will take 1 fire and ditch other

#

ARRRGHHH

#

that could've been weird behavior with :Wait()

#

lmao

proven yoke
#

I think that's it

#

that was what I was encountering

scarlet pecan
rough rivet
#

check this out

#

i don't think i sent this before?

#

it's from here

#

you guys should see if it's any good

scarlet pecan
# rough rivet https://github.com/roblox/signal-lua

It's basically a signal with :Connect() and nothing else, not even built-in asynchronicity support (thread usage) nor asynchronous error catching either 😭

local CreateSignal = require(createSignal)
local signal = CreateSignal()
local cn = signal:subscribe(fn)
cn:unsubscribe()
-- ^ that's EVERYTHING
rough rivet
#

as simple as it gets basically

#

aside from the strict typechecking

scarlet pecan
scarlet pecan
rough rivet
#

i couldn't even think of anything else

#

i guess the fact it's split up into multiple modules

#

for some reason

#

wow it even has a whole ass types module

#

INCREDIBLE!

stuck thorn
#

It does make development of module better, but it must have a reason

#

^ ie. network lib benefits from it as it's just multiple components

proven yoke
#

interesting

#

it passed everything

scarlet pecan
proven yoke
#

lmfao

stuck thorn
#

πŸ€”

proven yoke
#

@night tartan

night tartan
#

balright

rough rivet
#

test it

scarlet pecan
#

RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

rough rivet
#

oh LOL

rough rivet
#

I'M SORRY

#

to make up for it here's my signal module which is like really fast

return Instance.new('BindableEvent')
stuck thorn
#

you should try this lol

proven yoke
scarlet pecan
# stuck thorn <@852016627276972072> https://github.com/Vel136/Vetra/blob/master/src/Core/VeSig...

Class 3 when used correctly, this is legit a strong rival of SomeSignal, better & worse in some areas.

What I like:

  • :Fire() determines whether or not it should be completely Synchronous or respect each connection's synchronicity (faster on average than an Async-only Fire).
  • :OnceTimeout() & :OnceAsyncTimeout() seems like it could have its uses, basically a :Wait() but for an input function instead of a thread.
  • Has ordered priority

Small issues:

  • LITTLE TO NO TOOLTIPS NOR DOCUMENTATION. A few types are broken too due to typesolver updates I bet.
  • POSSIBLE BUG: Signals created via .all() don't self-destroy or reset their tracking after all of its input signals run, so they're effectively minor memory leaks after they fulfill their purpose if you forget to disconnect them.
  • There's quite a few boilerplate/unnecessary functions
    • :FireDeferred(), this is literally a task.defer wrapper with nothing new added...
    • :ConnectIf & :ConnectIfAsync are misleading, they don't perform the check before creating the connection like their names imply, they do it whenever the connection runs.
    • :WaitPriority(), nearly identical to :Wait() except it removes the one condition check for timeouts, unnecessary micro-optimization tbh.
  • Uses coroutine.resume for async connections, this may lead to hidden/hard-to-debug niche issues due to the engine.
#

I haven't done a deep dive into testing niche stuff like multiple signal nested usage yet, so I'm likely missing a bit of info & cannot guarantee yet if it's safe to use in all use-cases

snow plinth
#

#chat message

stuck thorn
#

Honestly I would like to believe this signal was helped with AI lul

stuck thorn
stuck thorn
#

LOL

scarlet pecan
#

No sane dev who uses --!strict would allow ts 😭

snow plinth
#

chat he might be onto something

stuck thorn
#

I was like "is this a named signal copy" just becaues of the type functions, but I think not

scarlet pecan
#

Completely different programming styles & greatly different signal structures, all good πŸ‘

stuck thorn
#

something doesn't compute here, some type functions are creepingly familiar

scarlet pecan
#

They do share the same usage of read & <Signature> in typing, but the similarities end there

#

The signal structures are still very different

stuck thorn
#

fair enough

stuck thorn
#

πŸ€”

scarlet pecan
#

Is it different for you?

stuck thorn
#

it's not a beta feature anymore

#

you can find the solver settings in workspace

#

(although by default, it's new type solver)

scarlet pecan
proven yoke
#

what even is class3

#

why does it have ordered priority

#

who wants that

snow plinth
proven yoke
#

still confused about why

stuck thorn
#

This was made out of spite, because roblox bindables are literally behind lol 😭

#

^ so is majority of roblox luau signals

proven yoke
#

bruh 😭

#

why does vesignal even have that then

#

what was his motivation to make it class3

scarlet pecan
# proven yoke what even is class3

Class 3 tldr:

  • Connections are ran from Oldest -> Newest
  • Everything that's meant to be synchronous in a connection is actually synchronous (run to completion), this needs to include nested Firing if the ran connection is still synchronous.
  • Connection mutations are optionally applied only after all connections are ran, so disconnections are no longer completely dependent on connection-ordering. Do note that the code within connections are still order-dependent.
scarlet pecan
proven yoke
#

so this is only to replicate bindable behavior fully

scarlet pecan
proven yoke
#

Ive never had a use case for it but Ig its a thing

scarlet pecan
#

Yee it's not necessary but it's convenient

proven yoke
#

bruh I see

stuck thorn