Lock between Lua lanes - lua

I am trying to use locks between 2 Lua lanes,but observed that both the lanes are entering lock_func simultaneously..Below is the snippet
Code Snippet
==================
require"lanes"
local linda = lanes.linda()
lock_func = lanes.genlock(linda,"M",1)
local function lock_func()
print("Lock Acquired")
while(true) do
end
end
local function readerThread()
print("readerThread acquiring lock")
lock_func()
end
local function writerThread()
print("writerThread acquiring lock")
lock_func()
end
Thread1= lanes.gen("*",{globals = _G},writerThread)
Thread2= lanes.gen("*",{globals = _G},readerThread)
T1 = Thread1()
T2 = Thread2()
T1:join()
T2:join()
From the ouput below we can see both the lanes have entered the lock_func function simultaneously
output
==================
writerThread acquiring lock
Lock Acquired
readerThread acquiring lock
Lock Acquired
Is there any problem with the implementation of the lock from the above code?

The implementation of locks in lua can be done as in the below code snippet. Only the print from writer or reader lane will be executed from the below code, as which ever lane acquiring the lock will go into an infinite loop(just to see locks are working as expected) & other lane will wait for the lock to get released.
require"lanes"
local linda = lanes.linda()
f = lanes.genlock(linda,"M",1)
local function readerThread()
require"lanes"
f(1)
print("readerThread acquiring lock")
while(true) do
end
f(-1)
end
local function writerThread()
require"lanes"
f(1)
print("writerThread acquiring lock")
while(true) do
end
f(-1)
end
Thread1= lanes.gen("*",{globals = _G},writerThread)
Thread2= lanes.gen("*",{globals = _G},readerThread)
T1 = Thread1()
T2 = Thread2()
T1:join()
T2:join()

Related

Use of Fork-Join in Verilog

I would like to do a task that checks in parallel one of the two statements commented below and that doesn't break the execution of the program that follows it:
The Task checks if startTx has been generated. It must wait for startTx signal 5 clock cycles. If the startTx is asserted, it prints a successful message. If not (after the timeout), it prints an error message and increases the error counter.
What I've done so far is:
task checkStart;
begin
fork
// evento 1
begin
waitCycles(5); // timeOut
$display("[Error! %t] Time Out has been reached", $time);
errors = errors + 1;
end
// evento 2
begin
#(posedge(startTx))
$display("[Info] startTx has been generated successfully");
end
join
disable fork;
end
endtask
But doesn't seem to be working as it apparently checks for both statements to be true and I would like something as 'join_any' from SystemVerilog that breaks whenever one of both statements become true.
This works without using the SystemVerilog join_any. Comment startTx or uncomment it to see the two conditions that occur.
module tb ();
bit SIGNAL;
bit startTx;
int errors;
task checkStart;
fork
// evento 1
begin : timeout
#500; // timeOut
$display("[Error! %t] Time Out has been reached", $time);
errors = errors + 1;
$finish;
end
// evento 2
begin :wait_for_signal
#(posedge(startTx))
$display("[Info] startTx has been generated successfully");
disable timeout;
end
//
join
//
$display("+++++ Finished checkStart ++++++");
endtask
initial
begin
checkStart();
// Do something else
#20;
$display("**** normal finish ****");
$finish;
end
initial
begin
#1;
// coment one of these at a time
//startTx = 1;
startTx = 0;
end
endmodule

Attempt to call global "Sicherheitskreis" (a nil value ) stack traceback

I'm trying to secure the doors of my CNC with switchs that send a Signal to my Laptop (I got Mach 4 on it). I created this Code that should make the Spindle stay still if the doors aren't locked, but I always get an error that says :
[string""]1576 attempt to call global 'SicherheitsKreis' (a Nil value) stack traceback:
I've tried to move the Code around and read topics on this, but Nothing works.
Does someone have a solution ?
Here's all my Code :
function SicherheitsKreis(Schliesserstate, Oeffnerstate)
if (Schliesserstate ==0 and Oeffnerstate ==1 ) then
mc.mcSpindleSetDirection(inst,0)
elseif (Schliesserstate == 1 and Oeffnerstate == 0 ) then
local sigh = mc.mcSignalGetHandle(inst, mc.OSIG_SPINDLEON);
local sigState = mc.mcSignalGet State(sigh);
if (sigState == 1) then
mc.mcSpindleSetDirection(inst,0)
else
mc.mcSpindleSetDirection(inst,1);
end
else
mc.mcSpindleSetDirection(inst,0)
end
end
if (mc.mcInEditor() == 1) then
SicherheitsKreis()
end
The Code that I'm using to call SicherheitsKreis is :
local inst = mc.mcGetInstance()
local hsigSchliesser = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT8);
local hsigOeffner = mc.mcSignalGetHandle (inst, mc.ISIG_INPUT9);
local Schliesserstate = mc.mcSignalGetState(hsigSchliesser);
local Oeffnerstate = mc.mcSignalGetState(hsigSchliesser);
SicherheitsKreis(Schliesserstate, Oeffnerstate)
This Script is typed in Mach 4 and the function is saved as a m function (nach4 has free m function that the user can customize) in the Memory of Mach 4 (for my Computer it is m146)
Your code:
function SicherheitsKreis(Schliesserstate, Oeffnerstate)
...
end
First possibility is that code is in some other function or other element, so it is not global. Second possibility is that you run SicherheitsKreis(Schliesserstate, Oeffnerstate) before loading this part of code. Third (very uncommon) is that you override it by SicherheitsKreis = nil or equivalent. There is no other possibilities.

How can I skip back a few seconds after pause in VLC Media Player?

I've searched this on the internet, but can't seem to find anything. I know there are hotkeys to skip back a few seconds, and I know there are hotkeys to to pause and play audio/video in VLC Media Player. However, I am using a single foot pedal for transcription and essentially need it to do both. I would like the pedal tap to pause the audio. Then, after tapping again, I would like it to play the audio, but skipping a few seconds back when doing so. Is this possible?
Save this code as rollback.lua and place it in Program Files\VideoLAN\VLC\lua\extensions folder. Then activate it through View > Rollback X Seconds.
function descriptor()
return {
title = "Rollback X Seconds",
capabilities = {"input-listener", "playing-listener"}
}
end
function activate()
end
function close()
end
function deactivate()
end
function input_changed()
end
function playing_changed()
local TIME_DELTA = -3
if vlc.playlist.status()=="paused" then
local timePassed = vlc.var.get(vlc.object.input(), "time")
local newTime = timePassed + TIME_DELTA
vlc.osd.message(TIME_DELTA, vlc.osd.channel_register(), "top-left", 1400000)
vlc.var.set(vlc.object.input(), "time", newTime)
end
end
Change the variable TIME_DELTA to whatever time change you want on pause
I expanded on the code provided by Tee by adding a GUI.
I would also like to add a few details of how to get it working.
Create a empty file, name it rollback.lua.
Copy the code provided underneath this list, paste into the file and save.
Move the file to VLCs folder for lua extensions, it should look something like this:
c:/Program Files/VideoLAN/VLC/lua/extensions
Restart VLC player.
Activate the script by going to (Note! Needs to be done each time you start VLC to use the plugin)
view > Rollback X Seconds
Select time in seconds you want to rollback and hit save (or save and close).
In order to get your pedal working with this script, simply configure the hotkey in VLC for play/pause toggle.
VLC > Tools > Preferences > Hotkeys > Set "Play/Pause" Global value to be your pedal.
(After you change a Global hotkey, you need to restart VLC in order to get it working...)
The code:
micro_second_unit = 1000000
TIME_DELTA = 1 --Default,
SHOW_OUTPUT = true
TIME_TO_DISPLAY = 1.5 --Default
function descriptor()
return {
title = "Rollback X Seconds",
capabilities = {"input-listener", "playing-listener"}
}
end
function activate()
dlg = vlc.dialog("Rollback X Seconds")
rollback_input = dlg:add_text_input("1", 2, 1 )
rollback_input_label = dlg:add_label("Seconds to back", 1, 1)
checkBox = dlg:add_check_box("Show output time ", wasChecked, 3, 3 )
timeTo_display_box = dlg:add_text_input(1.5, 2 ,3)
timeTo_display_box_label = dlg:add_label("Seconds To Display", 1, 3)
w2 = dlg:add_button("Save settings", change_step, 3, 4, 1, 1)
w2 = dlg:add_button("Save and close", updateAndClose, 3, 5, 1, 1)
done = dlg:add_label( "" , 3, 6)
end
function close()
end
function deactivate()
vlc.deactivate()
end
function input_changed()
end
function playing_changed()
if vlc.playlist.status()=="paused" then
local timePassed = tonumber(vlc.var.get(vlc.object.input(), "time"))
local newTime = timePassed - seconds_to_microsecond(TIME_DELTA)
local newTime_inSeconds = (newTime/1000000)
local newTime_inMinutes = (newTime_inSeconds/60)
local newTime_inSeconds_restOfMin = math.fmod(newTime_inSeconds,60)
local newTime_str = math.floor(newTime_inMinutes) .. "min " .. round(newTime_inSeconds_restOfMin,1) .."sec"
local timePassed_inSeconds = (timePassed/1000000)
local timePassed_inMinutes = (timePassed_inSeconds/60)
local timePassed_inSeconds_restOfMin = math.fmod(timePassed_inSeconds,60)
local timePassed_str = math.floor(timePassed_inMinutes) .. "min " .. round(timePassed_inSeconds_restOfMin,1) .."sec"
if SHOW_OUTPUT == true then
vlc.osd.message("Seconds to Back:" .. TIME_DELTA .. "sec", vlc.osd.channel_register(), "top-right", seconds_to_microsecond(TIME_TO_DISPLAY))
vlc.osd.message("New time:" .. newTime_str, vlc.osd.channel_register(), "top-left", seconds_to_microsecond(TIME_TO_DISPLAY))
vlc.osd.message("Old time:" .. timePassed_str, vlc.osd.channel_register(), "bottom-left", seconds_to_microsecond(TIME_TO_DISPLAY))
end
vlc.var.set(vlc.object.input(), "time", newTime)
end
end
function updateAndClose()
change_step()
dlg:delete()
end
function change_step()
done:set_text("Saved")
TIME_DELTA = tonumber(rollback_input:get_text())
SHOW_OUTPUT = checkBox:get_checked()
if SHOW_OUTPUT == true then
TIME_TO_DISPLAY = tonumber(timeTo_display_box:get_text())
end
end
function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
function microsecond_to_seconds(timeToConvert)
return timeToConvert / micro_second_unit;
end
function seconds_to_microsecond(timeToConvert)
return timeToConvert * micro_second_unit;
end
This will work just like Tee's script, the video will jump back each time it's paused.
Only difference is that you can set the amount of time to jump back each time you start the script.
The amount is given in seconds, however you can use decimals for more control...
There's also a checkbox you can tick if you want to display information about the jump.
I also want to thank Tee for his answer!
This is the first lua code I've written (or rather, modified) and it's a bit messy, but it works and I have used it every day since so I thought I might as well share it.

(Lua) Why is my producer-consumer Lua coroutines experiment not yielding the expected resault?

I have created the following two coroutines a producer and a consumer in an attempt to learn/understand the coroutines.
function count01to10()
for i = 1, 10 do
coroutine.yield(i)
end
end
function printNumber(number)
while number ~= nil do
print("Counter: ", number)
coroutine.yield()
end
end
function main()
local number = 0
print("Creating coroutines")
local counter = coroutine.create(count01to10)
local printer = coroutine.create(printNumber)
print("Executing coroutines")
while (10 > number) do
isSuccessuful, number = coroutine.resume(counter)
print("counter: ", coroutine.status(counter))
coroutine.resume(printer, number)
print("printer: ", coroutine.status(printer))
end
print("Finished")
end
main()
The output is:
Creating coroutines
Executing coroutines
counter: suspended
Counter: 1
printer: suspended
counter: suspended
Counter: 1
printer: suspended
...
Counter: 1
printer: suspended
Finished
I am expecting the ouput to print out the numbers 1 to 10. Why is this not happening and is that a proper way to use coroutines?
A coroutine resumes at the same point where it yield (or just after it), not at the beginning.
Your code for printNumber does not change number, so the output you get is not surprising.
To fix this, use number=coroutine.yield() in printNumber.
The arguments passed to resume are returned by yield.

Lua metatable Objects cannot be purge from memory?

I'm using a proprietary platform that reported memory usage in realtime on screen. I decided to use a Class.lua I found on http://lua-users.org/wiki/SimpleLuaClasses
However, I noticed memory issues when purging object created by this using a simple Account class. Specifically, I would start with say 146k of memory used, create 1000 objects of a class that just holds an integer instance variable and store each object into a table.
The memory used is now 300k
I would then exit, iterating through the table and setting each element in the table to nil. But would never get back the 146k, usually after this I am left using 210k or something similar. If I run the load sequence again during the same session, it does not exceed 300k so it is not a memory leak.
I have tried creating 1000 integers in a table and setting these to nil, which does give me back 146k.
In addition I've tried a simpler class file (Account2.lua) that doesn't rely on a class.lua. This still incurs memory fragmentation but not as much as the one that uses Class.lua
Can anybody explain what is going on here? How can I purge these objects and get back the memory?
here is the code
--------Class.lua------
-- class.lua
-- Compatible with Lua 5.1 (not 5.0).
--http://lua-users.org/wiki/SimpleLuaClasses
function class(base,ctor)
local c = {} -- a new class instance
if not ctor and type(base) == 'function' then
ctor = base
base = nil
elseif type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a ctor which can be called by ()
local mt = {}
mt.__call = function(class_tbl,...)
local obj = {}
setmetatable(obj,c)
if ctor then
ctor(obj,...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj,...)
end
end
return obj
end
c.init = ctor
c.instanceOf = function(self,klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c,mt)
return c
end
--------Account.lua------
--Import Class template
require 'class'
local classname = "Account"
--Declare class Constructor
Account = class(function(acc,balance)
--Instance variables declared here.
if(balance ~= nil)then
acc.balance = balance
else
--default value
acc.balance = 2097
end
acc.classname = classname
end)
--------Account2.lua------
local account2 = {}
account2.classname = "unnamed"
account2.balance = 2097
-----------Constructor 1
do
local metatable = {
__index = account2;
}
function Account2()
return setmetatable({}, metatable);
end
end
--------Main.lua------
require 'Account'
require 'Account2'
MAX_OBJ = 5000;
test_value = 1000;
Obj_Table = {};
MODE_ACC0 = 0 --integers
MODE_ACC1 = 1 --Account
MODE_ACC2 = 2 --Account2
TEST_MODE = MODE_ACC0;
Lua_mem = 0;
function Load()
for i=1, MAX_OBJ do
if(TEST_MODE == MODE_ACC0 )then
table.insert(Obj_Table, test_value);
elseif(TEST_MODE == MODE_ACC1 )then
table.insert(Obj_Table, Account(test_value)); --Account.lua
elseif(TEST_MODE == MODE_ACC2 )then
table.insert(Obj_Table, Account2()); --Account2.lua
Obj_Table[i].balance = test_value;
end
end
end
function Purge()
--metatable purge
if(TEST_MODE ~= MODE_ACC0)then
--purge stage 0:
print("set each elements metatable to nil")
for i=1, MAX_OBJ do
setmetatable(Obj_Table[i], nil);
end
end
--purge stage 1:
print("set table element to nil")
for i=1, MAX_OBJ do
Obj_Table[i] = nil;
end
--purge stage 2:
print("start table.remove...");
for i=1, MAX_OBJ do
table.remove(Obj_Table, i);
end
print("...end table.remove");
--purge stage 3:
print("create new object_table {}");
Obj_Table= {};
--purge stage 4:
print("collectgarbage('collect')");
collectgarbage('collect');
end
--Loop callback, called every tick
function OnUpdate()
Lua_mem = collectgarbage('count');
collectgarbage('collect');
end
--Loop rendering callback
function OnRender()
DrawText(Lua_mem );
end
-------------------
--NOTE:
--code starts in idle awaiting input from user
--On first input, runs Load(), on exit runs Purge()
--Where DrawText() draws the string parameter passed, to screen.
--Update
I've updated the code with suggestions from comments below, and will post my findings later today.
--Update 2
Well I've tried the above code, and it does seem collectgarbage("count") reports lua giving me back all the memory in all three scenarios.
Here are my results for collectgarbage('count')
ACC0
- On start: 25.567K used
- On Load: 89.334K used
- On Purge: 25.567K used
ACC1
- On start: 25.567K used
- On Load: 440.567k used
- On Purge: 25.567K used
ACC2
- On start: 25.327K used
- On Load: 245.34K used
- On Purge: 25.327K used
You need to force the garbage collector to reclaim the memory (see collectgarbage("collect")).
Main.lua:
--purge stage 0:
print("set each elements metatable to nil")
for i=1, MAX_OBJ do
setmetatable(Obj_Table[i], nil);
end
According to the documentation of Lua you can not reset a tables metatable by trying to set it to nil. It just equals the function getmetatable(). So the objects keep being linked.
Most dynamic languages don't really release memory back to system, but keep it ready for future allocations instead. Try to create some objects after Lua reported memory decrease - Lua should use this freed memory it kept to yourself and platform memory consumption won't increase.

Resources