How do I make timers not run into eachother

Hey,

I have these 3 timers and they eventually run into eachother and print 2 things in chat at once, how do I prevent this?

[lua]
timer.Create(“chatnotifydonate”, 60, 0, function()
chat.AddText(Color(255,255,255), “Wanna “,Color(100, 255, 100), “donate”, Color(255,255,255),”? Type !donate in chat.”)
end)

timer.Create(“chatnotifyrules”, 40, 0, function()
chat.AddText(Color(255,255,255), “To see server “,Color(255, 100, 100), “rules”, Color(255,255,255),” type !rules in chat.”)
end)

timer.Create(“chatnotifyadmin”, 100, 0, function()
chat.AddText(Color(255,255,255), “To contact an “,Color(100, 100, 255), “admin”, Color(255,255,255),”, Type @ then what you want to say after it in chat.”)
end)

[/lua]

Create them at different times.

Right now you create 3 timers with periods of 60, 40, and 100 at the same time.

This means that two of them will trigger at once each 120 seconds, and all of them will get triggered at once each 600 seconds.

To solve this, create them at different times, so that their activation moments dont overlap. This is really easy.

[lua]
timer.Simple(15, function()
timer.Create(“chatnotifydonate”, 60, 0, function()
chat.AddText(Color(255,255,255), “Wanna “,Color(100, 255, 100), “donate”, Color(255,255,255),”? Type !donate in chat.”)
end)
end)

timer.Simple(35, function()
timer.Create(“chatnotifyrules”, 40, 0, function()
chat.AddText(Color(255,255,255), “To see server “,Color(255, 100, 100), “rules”, Color(255,255,255),” type !rules in chat.”)
end)
end)

timer.Simple(25, function()
timer.Create(“chatnotifyadmin”, 100, 0, function()
chat.AddText(Color(255,255,255), “To contact an “,Color(100, 100, 255), “admin”, Color(255,255,255),”, Type @ then what you want to say after it in chat.”)
end)
end)
[/lua]

Something like this will work. You might have to play around with the offsets a bit.

Thankyou friend ill test to see if it works now

Clashes will still occur with this arrangement. I can prove it with maths.


let t = time elapsed in seconds

--timer 1
let start1 = 15
elap1 = t - start1

--timer2
let start2 = 35
elap2 = t - start2

--timer3
let start3 = 25
elap3 = t - start3

-----
simulate clash between timer1 and timer 2
when elap1/60 == 1 and elap2/40 == 1
->
(t - 15)/60 = (t - 35)/40
t - 15 = 1.5 * (t - 35)
t - 15 = 1.5t - 52.5
0.5t = 37.5
t= 75 seconds

therefore, a clash between timer1 and timer2 will occur at 75 seconds



Don’t believe me? Wait 75 seconds and try.

I did say that you might have to play around with the offsets a bit. It was just an example.
I tried using wolframalpha to find a non-clashing configuration but couldn’t be arsed.

Just using the same period but a different phase works.

Just use different prime numbers… Programming languages hash functions use them and the probability to overlap is nearly zero.
Here’s a list http://primes.utm.edu/lists/small/10000.txt

This.

Also, another, really easy way to make it so messages don’t overlap, is to use a list of messages and print them in order, one after another. Though this may not be what you are looking for.

[lua]
– a table of tables
– each entry in the table
– signifies an announcement
– the “message” key is
– the message that will be printed
– the “delay” key is the time
– it will take to print the next message
– after this one

local messages = {
{message = {Color(255, 255, 255), “message 1”}, delay = 30},
{message = {Color(255, 255, 255), “message 2”}, delay = 20},
{message = {Color(255, 255, 255), “message 3”}, delay = 10},
}

– keeps track of what message we should print now
local i = 1

function print_message()
chat.AddText(unpack(messages*.message))
i = i + 1

-- start a timer with the current delay
timer.Create("rotated_messages", message*.delay, 1, function()
	-- print the message again
	print_message()
end)

end

[/lua]

This is not really true. Two timers with different prime periods will overlap when at t = p1 * p2.

Yes, but let’s look at his timers, his first one is 60 seconds, the nearest prime is 59 (or 61), and the last one 100, nearest prime 101. 101 * 59= 5959 -> overlap after 99 minutes, over 1 h 39 minutes. So it’s rare, and I don’t know if the probability of overlapping by using different phases is lower (But that would be a very interesting question!).

If you make three timers with a period of 60, and offset them by 0, 20, and 40 seconds, they will never overlap, because they will running 20 seconds apart from each other all the time.

In the end it depends what phases and periods you use.

The problem of finding a configuration of offsets and different periods, such that they don’t overlap is a bit more difficult, but not impossible. Though I don’t have the patience to sit down and think through the math that is required to find such configurations.

Is there nothing like a mutex or lock available in gmod? Even waiting for non-atomic booleans would be better than hoping for two timers not to align.

@op: The concept to solve this problem is here: https://en.wikipedia.org/wiki/Lock_(computer_science)
But I don’t know if it’s possible to implement it atomically in GMod

No Lua in Garry’s Mod in executed in parallel. Every Lua operation is always atomic and every function is atomic until you start using coroutines.

Timers will never execute at the time time, but rather sequentially one-after-the-other in the same tick.

You could keep the last time a message has been printed in a variable, something like
[lua]
local last_print = 0
[/lua]
And set it to CurTime() each time a message is printed. Then, before printing a new one, you check if the time since last message is greater than some amount (say, 10 seconds), you postpone the timer until it can print it’s message.

This would be far easier to implement in a Think hook than a timer, but the idea stays.
It certainly is possible, but, honestly, I think this is overcomplicating the issue. Such a solution definitely could have place in an advanced announcement system, but I think a simpler solution will work for OP.

EDIT:

Like Willox said, the concept of a lock is probably inapplicable here. However you gave me this idea.