Announcement

Collapse
No announcement yet.

Lua Lanes with MemoryEx

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    actually I'm getting 'AllocateEx' is a nil value now and its pointing to my side of the code here:

    Code:
    local hBuffer = MemoryEx.AllocateEx(1024);

    Comment


    • #17
      Here is a snippet I made, it's a kind of Event Driven programming implementation:

      PHP Code:
      function setText(txt)
          
      local t MemoryEx.Allocate(#txt + 1)
          
      MemoryEx.String(t, -1MEMEX_ASCIItxt)
          
      local y Bitwise.Or(Bitwise.ASL(0,16),0)
          
      local x Bitwise.Or(Bitwise.ASL(0,16),y)
          if 
      User32.SendMessageA(StatusBar.Handle,0x401,x,t) == 0 then
              MemoryEx
      .Free(t)
              return 
      false"Can't set text"
          
      else
              
      MemoryEx.Free(t)
              return 
      true"OK"
          
      end
      end

      EventManager 
      = {
          
      addListener = function(eventNamecallback)
              if 
      type(EventManager.events[eventName]) == 'nil' then
                  EventManager
      .events[eventName] = {}
              
      end
              table
      .insert(EventManager.events[eventName], callback);
          
      end,
          
      events = {},
          
      trigger = function(eventNamedata)
              if 
      type(EventManager.events[eventName]) == 'table' then
                  
      for icallback in pairs(EventManager.events[eventName]) do
                      
      data callback(data);
                  
      end
              end
          end
      ,
      }

      lanes = require "lanes"

      EventManager.addListener('setText'setText);

      function 
      sendText()
          
      local dummyText "Hello world";
          -- 
      Set a timer for this demo function
          
      local start os.time();
          while 
      true do
              
      local diff os.time() - start;
              if 
      diff >= 10 then
                  
      break;
              
      end
          end
          EventManager
      .trigger('setText'dummyText);
          return 
      nil;
      end

      demoFunction 
      lanes.gen("*", {globals=_G}, sendText);
      demoFunction(); 
      Im still don't know why you are putting a setText function inside a lane, I don't have the full code to be in context lol

      Comment


      • #18
        Happy new year everyone! Best wishes from the NL

        Great to see this thread, I've never actually tested MX and LH modules inside Lanes yet, this is rather interesting!
        Bas Groothedde
        Imagine Programming :: Blog

        AMS8 Plugins
        IMXLH Compiler

        Comment


        • #19
          Eagle, I have installed lua 5.1.5 and lua lanes 3.7 and I was able to load C functions. Since version 3.0, lua lanes no longer copy C functions pointer but it doesn't mean you can't pass it to the new Lane. I tested with lua socket 3.0 module. I don't have a windows pc to test if it works with AMS but here is the code:

          PHP Code:
          socket = require "socket"
          lanes = require"lanes".configure() -- This is how lua lanes 3.7 is loaded
          function x() socket.sleep(1) print('done'end -- Just a dummy function
          lanes.gen('*', {globals _Grequired={'socket'}}, x)
          y() 
          If someone can test it would be great

          Comment


          • #20
            Originally posted by webultra View Post
            Im still don't know why you are putting a setText function inside a lane, I don't have the full code to be in context lol
            It was only inside the Lane to see if it worked within it as it never outside it but it don't work either way lol, all it is is using MemoryEx to have custom controls like ComBoBoxEx and ListView but having the Lane dealing with keeping them up to date so not to block the main thread.

            Comment


            • #21
              I was using the following code on a project using the alien module (you can use it as an example using the user32 dll functions. This code was detecting if there were other application instances running, and sending to it a command arg, just to prevent from opening more than 2 application windows.

              PHP Code:
              --------Globals User32.dll functions using alien module--------
              require
              "alien";
              user alien.load 'user32.dll';
              user.SendMessageA:types{ret "long"abi 'stdcall'"int""int""long""pointer"};
              user.EnumChildWindows:types{ret "long"abi 'stdcall'"int""callback""pointer"};
              function 
              SendTo(nHandlesMessage)
                  
              local SetText user.SendMessageA;
                  
              local a SetText(nHandle120sMessage);
                  
              SetText(nHandle256130);
              end
              function GetFrom(nHandle)
                  
              local GetText user.SendMessageA;
                  
              local buf alien.buffer(512);
                  
              local a GetText(nHandle13512buf);
                  return 
              abuf:tostring();--Lengthstring
              end
              function EnumChildAndSend(n)
                  
              local eee user.EnumChildWindows;
                  
              eee(nhwnd_callbacknil);
              end
              function each_hwnd (hwnd,p)
                  
              local a,GetFrom(hwnd);
                  if 
              == "receiver" then
                      SendTo
              (hwndcmd)
                  
              end
                  
              return 1;
              end
              hwnd_callback 
              alien.callback(each_hwnd,{"int","pointer",abi="stdcall"});

              -----
              On Startup
              local tP 
              Window.EnumerateTitles(true);
              if 
              tP then
                  
              for handletitle in pairs(tP) do
                      if 
              title == "Generic Updater" then
                          
              if handle ~= Application.GetWndHandle() then
                              Window
              .Restore(handle);
                              if 
              _CommandLineArgs and #_CommandLineArgs > 0 then
                                  
              cmd table.concat(_CommandLineArgs" ");
                                  
              EnumChildAndSend(handlecmd)
                              
              end
                              os
              .exit();
                          
              end
                      end
                  end
              end 
              An example using the Status bar SetText function could be (untested):

              PHP Code:
              require"alien";
              user alien.load 'user32.dll';
              user.SendMessageA:types{ret "long"abi 'stdcall'"int""int""long""pointer"};
              function 
              SendText(nHandlesMessage)
                  
              local SetText user.SendMessageA;
                  
              local a SetText(nHandle10250sMessage);
              end 

              Comment


              • #22
                hi dudes lua lanes v3.7.7.0 will work fine with standard modules, however the same issues since
                v3.0beta with not loading c pointers and deep user data (Ams tables and functions etc) via _G.

                I am when time permits working on a 'filtered' _G table function and other stuff including working
                through the source code of Lanes and getting the registering of all _G into the lanes lookup database.

                Also attempting to get rid of a few bugs in Lanes v2.2, so will post again if any worthwhile fixes etc

                Comment


                • #23
                  @Eagle, if you can get MemoryEx passed in to the lane then AMS will reach a whole new level.

                  Comment


                  • #24
                    After some _G sleuthing within a lua lane I have come up with several ways to fix MemoryEx plugin not being initialized properly within a lane function,
                    when the MemoryEx plugin is present in the AMS global state and _G is passed
                    to the lane call unaltered.

                    An important note regardless of which method you use:

                    MemoryEx v2.3 requires access to Ams global tables: Application, String, Table,
                    _tblErrorMessages and possibly _tblNotificationMessages

                    so these must be passed to the lane call so they are present in the new state _G
                    ( see method 2 for passing a filtered minimum Ams _G table to a new lane )

                    Method 1.

                    prior to your code loading-registering the MemoryEx plugin in a lane main function thread, simply remove MemoryEx plugins 'OOP' tables from the lane Global environment (this assumes you have passed the Ams _G table in the new lane call) :

                    Code:
                    -- MemoryEx plugin fix (no mods to Ams _G table required) --
                    
                    	--set AssemblerOOP, LibraryOOP, MemoryExOOP to nil in lane
                    
                    	AssemblerOOP = nil; LibraryOOP = nil; MemoryExOOP = nil;
                    
                            --now load the MemoryEx plugin from any valid path:
                    
                            local path = _SourceFolder.."\\Data\\MemoryEx.lmd";	
                            local bool, err = pcall(package.loadlib(path, "irPlg_Action_RegisterActions"));

                    Method 2.

                    Create a filtered _G table to pass to the new lane call:


                    Code:
                    -------------_FilterLaneGlobalTable_Min_MemoryEx_Fix_V1()-----------
                    --[[                                                              --
                    	Function to enable MemoryEx v2.3 to function as expected      --
                    	when run within a Lua Lane using Lanes version 2.2.0.1        -- 
                    	Note: this function fixes MemoryEx functionality within       --
                    	a running lane if the MemoryEx plugin was loaded at runtime   --
                    	( or it's functionality registered in Ams Global Table _G )   --
                    	                                                              --
                    	example:  _C = _FilterLaneGlobalTable_Min_MemoryEx_Fix_V1()   --
                    	 (you would then pass the new _C table to a lane)             -- 
                    	]]
                    	
                    	
                    	local function _FilterLaneGlobalTable_Min_MemoryEx_Fix_V1()
                    	--compatible with Lua Lanes versions v2x only
                    	
                    	local t2 = {};
                    	
                    	--cycle input table and apply filters
                    	
                    	for k,v in pairs(_G) do
                    	
                    		local vt = type(v);
                    		
                    		--pass no existing global functions to new table
                    		if vt ~= 'function' then
                    		
                    			--check if table and for minimal required tables:
                    			
                    			if vt == 'table' then
                    				--[[MemoryEx plugin v2.3 requires Ams Global tables: Application, String, Table
                    					also add Ams error checking tables, Debug, Dialog and _CommandLineArgs
                    					]]
                    				
                    				if k == 'Application' or k == 'String' or k == 'Table'
                    				   or k == '_tblErrorMessages' or k == '_tblNotificationMessages'
                    				   or k == 'Debug' or k == 'Dialog' or k == '_CommandLineArgs' then
                    				   
                    					t2[k] = v; --add filtered tables only
                    					
                    				end
                    				
                    			else
                    			
                    				--copy the minimum reccommended Ams constants for any 'lane':
                    								
                    				local s = String.Mid(k,1,1); --look for underscore _
                    				
                    				if s == '_' then
                    				
                    					--  _IR_ProductID , _VERSION , _WindowsFolder, _SystemFolder ,
                    					--   , _ProgramFilesFolder , _DesktopFolder , _DesktopFolderCommon ,
                    					--  _TempFolder , _SourceDrive , _SourceFolder, _SourceFilename , _LastErrorMessage
                    				
                    					t2[k] = v; --add filtered constants only
                    					
                    				end
                    						
                    			end --table and mimimal constants
                    							
                    		end --not a function
                    				
                    	end --input table cycle
                    	
                    	return t2; --the base filterd table Copy
                    
                    end
                    	
                    ------------End of _FilterLaneGlobalTable_Min_MemoryEx_Fix_V1() ----    
                    --------------------------------------------------------------------
                    
                    _C = _FilterLaneGlobalTable_Min_MemoryEx_Fix_V1();

                    (yes many ams functions and methods do not work within a lane using lua lanes v2.2)


                    hth

                    SharedMemory previously allocated via code in main Ams state IS accessable via a lane state
                    Last edited by Eagle; 04-15-2014, 01:31 AM. Reason: additional info

                    Comment


                    • #25
                      How to load a modules lua script using loadstring

                      example for initializing Lua Lanes v2.2x without the need for actual lanes.lua present

                      add this to Globals:

                      Code:
                      ------------------------------------------------------------------
                      ------------Lanes Lua via loadstring -----------------------------
                      
                      function LanesV2x_Init()
                      
                      local s_LanesV2Lua = [[
                      
                      -- modified v2.2.0.1 script to be later lanes and Lua 5.2 compatible
                      -- module is depricated in lua 5.2 so 'require' will suffice
                      -- so load to a table and be done with it
                      
                      local core = assert(require "lua51-lanes");
                      assert(type(core)=="table");
                      local lanes = {};
                      local thread_new = assert(core.thread_new);
                      local _single= assert(core._single);
                      local _version= assert(core._version);
                      local now_secs= assert(core.now_secs);
                      local wakeup_conv= assert(core.wakeup_conv);
                      local max_prio= assert(core.max_prio);
                      -- Cache globals for code that might run under sandboxing 
                      local assert= assert;
                      local string_gmatch= assert(string.gmatch);
                      local select= assert(select);
                      local type= assert(type);
                      local pairs= assert(pairs);
                      local tostring= assert(tostring);
                      local error= assert(error);
                      
                      local function WR(str)
                          io.stderr:write(str.."\n");
                      end
                      
                      local function DUMP(tbl)
                          if not tbl then return end
                          local str="";
                          for k,v in pairs(tbl) do
                              str= str..k.."="..tostring(v).."\n";
                          end
                          WR(str);
                      end
                      
                      local valid_libs= {
                          ["package"]= true,
                          ["table"]= true,
                          ["io"]= true,
                          ["os"]= true,
                          ["string"]= true,
                          ["math"]= true,
                          ["debug"]= true,
                          ["bit32"] = true, -- Lua 5.2 only, ignored silently under 5.1
                          --
                          ["base"]= true,
                          ["coroutine"]= true, -- part of "base" in Lua 5.1
                          ["*"]= true
                      };
                      
                      local function gen( ... )
                          local opt= {};
                          local libs= nil;
                          local lev= 2;  -- level for errors
                          local n= select('#',...);    
                          if n==0 then
                              error("No parameters!");
                          end
                      
                          for i=1,n-1 do
                              local v= select(i,...);
                              if type(v)=="string" then
                                  libs= libs and libs..","..v or v;
                              elseif type(v)=="table" then
                                  for k,vv in pairs(v) do
                                      opt[k]= vv;
                                  end
                              elseif v==nil then
                                  -- skip
                              else
                                  error("Bad parameter: "..tostring(v));
                              end
                          end
                      
                          local func= select(n,...)
                          local functype = type(func)
                          if functype ~= "function" and functype ~= "string" then
                              error("Last parameter not function or string: "..tostring(func));
                          end
                      
                          if libs then
                              for s in string_gmatch(libs, "[%a*]+") do
                                  if not valid_libs[s] then
                                      error("Bad library name: "..s);
                                  end
                              end
                          end
                          
                          local prio, cs, g_tbl, packagepath, packagecpath
                      
                          for k,v in pairs(opt) do
                              if k=="priority" then prio= v
                              elseif k=="cancelstep" then cs= (v==true) and 100 or
                                                              (v==false) and 0 or 
                                                              type(v)=="number" and v or
                                                              error("Bad cancelstep: "..tostring(v), lev)
                              elseif k=="globals" then g_tbl= v
                              elseif k=="packagepath" then packagepath= v
                              elseif k=="packagecpath" then packagecpath= v
                              elseif k==1 then error("unkeyed option: ".. tostring(v), lev)
                              else error("Bad option: ".. tostring(k), lev)
                              end
                          end
                          -- Lane generator    
                          return function(...)
                                    return thread_new(func, libs, cs, prio, g_tbl, packagepath, packagecpath, ...) -- args
                                 end
                      end
                      
                      local linda = core.linda;
                      
                      ---=== Timers ===---
                      --next three lines from v3x 
                      local timer = function() error "timers are not active" end
                      local timer_lane = nil;
                      local timers = timer;
                      ----------------------
                      local want_timers = true;
                      if want_timers then
                      
                      local timer_gateway= assert(core.timer_gateway);
                      local TGW_KEY= "(timer control)";
                      local first_time_key= "first time";
                      
                      local first_time= timer_gateway:get(first_time_key) == nil
                      timer_gateway:set(first_time_key,true);
                      -- Timer lane; initialize only on the first 'require "lanes"' instance (which naturally has 'table' always declared)
                      if first_time then
                          local table_remove= assert(table.remove);
                          local table_insert= assert(table.insert);
                          local collection= {};
                      
                          local function set_timer(linda, key, wakeup_at, period)
                      
                              assert(wakeup_at==nil or wakeup_at>0.0);
                              assert(period==nil or period>0.0);
                              local linda_deep= linda:deep();
                              assert(linda_deep);                
                              local t1= collection[linda_deep];
                              if not t1 then
                                  t1= {[linda_deep]= linda};
                                  collection[linda_deep]= t1;
                              end    
                              if wakeup_at==nil then            
                                  t1[key]= nil;
                                  local empty= true;
                                  for k,_ in pairs(t1) do
                                      if k~= linda_deep then
                                          empty= false; break
                                      end
                                  end
                                  if empty then
                                      collection[linda_deep]= nil;
                                  end    
                              else                        
                                  local t2= t1[key];
                                  if not t2 then
                                      t2= {}; t1[key]= t2;
                                  end    
                                  t2[1]= wakeup_at;
                                  t2[2]= period;
                              end
                          end    
                          
                          local function check_timers()
                              local now= now_secs();
                              local next_wakeup
                              for linda_deep,t1 in pairs(collection) do
                                  for key,t2 in pairs(t1) do                
                                      if key==linda_deep then
                                          
                                      else                    
                                          local wakeup_at= t2[1];
                                          local period= t2[2];                    
                                          if wakeup_at <= now then    
                                              local linda= t1[linda_deep];
                                              assert(linda);    
                                              linda:set(key, now);                        
                                              if not period then                            
                                                  t1[key]= nil;
                                                  wakeup_at= nil;
                                              else                                                        
                                                  repeat
                                                      wakeup_at= wakeup_at+period;
                                                  until wakeup_at > now    
                                                  t2[1]= wakeup_at;
                                              end
                                          end
                                          
                                          if wakeup_at and ((not next_wakeup) or (wakeup_at < next_wakeup)) then
                                              next_wakeup= wakeup_at;
                                          end 
                                      end
                                  end
                              end
                              
                              return next_wakeup;
                          end
                             
                          gen( "io,package", {priority=max_prio}, function()
                              set_debug_threadname("LanesTimer")
                              while true do
                                  local next_wakeup= check_timers();
                                  local secs;
                                  if next_wakeup then
                                      secs =  next_wakeup - now_secs();
                                      if secs < 0 then secs = 0 end
                                  end
                                  local linda= timer_gateway:receive(secs, TGW_KEY);
                                  if linda then
                                      local key= timer_gateway:receive(0.0, TGW_KEY);
                                      local wakeup_at= timer_gateway:receive(0.0, TGW_KEY);
                                      local period= timer_gateway:receive(0.0, TGW_KEY);
                                      assert(key and wakeup_at and period);
                                      set_timer(linda, key, wakeup_at, period>0 and period or nil);
                                  end
                              end
                          end )()
                      end
                      
                      local function timer(linda, key, a, period)
                      
                          if a==0.0 then                
                              linda:set(key, now_secs());
                              if not period or period==0.0 then
                                  timer_gateway:send(TGW_KEY, linda, key, nil, nil);
                                  return;
                              end
                              a= period;
                          end
                      
                          local wakeup_at= type(a)=="table" and wakeup_conv(a)
                                                             or now_secs()+a
                          
                          timer_gateway:send(TGW_KEY, linda, key, wakeup_at, period);
                      end
                      
                      end -- want_timers
                      
                      local function genlock( linda, key, N )
                          linda:limit(key,N);
                          linda:set(key,nil);
                          
                          local function trues(n)
                              if n>0 then return true,trues(n-1) end
                          end
                      
                          return
                          function(M)
                              if M>0 then            
                                  linda:send(nil, key, trues(M));
                              else
                                  for i=1,-M do
                                      linda:receive(key);
                                  end
                              end
                          end
                      end
                      
                      local function genatomic(linda, key, initial_val)
                          linda:limit(key,2);
                          linda:set(key,initial_val or 0.0);
                      
                          return
                          function(diff)        
                              linda:send(nil, key, true);
                              local val= linda:get(key) + (diff or 1.0);
                              linda:set(key, val);
                              return val;
                          end
                      end
                      
                      -- populate the 'lanes' table (modified from v3x and later)
                      
                      	--lanes.require = assert(core.require, 'core.require')
                      	lanes.gen = assert(gen, 'gen')
                      	lanes.linda = assert(core.linda, 'core.linda')
                      	lanes.cancel_error = assert(core.cancel_error, 'core.cancel_error')
                      	--lanes.nameof = assert(core.nameof, 'core.nameof')
                      	lanes.threads = assert(core.threads or function() error "lane tracking is not available" end, 'core.threads') -- core.threads isn't registered if settings.track_lanes is false
                      	--lanes.set_thread_priority = assert(core.set_thread_priority, 'core.set_thread_priority')
                      	lanes.timer = assert(timer, 'timer')
                      	--lanes.timer_lane = assert(timer_lane, 'timer_lane')
                      	lanes.timers = assert(timers, 'timers')
                      	lanes.genlock = assert(genlock, 'genlock')
                      	lanes.now_secs = assert(core.now_secs, 'core.now_secs')
                      	lanes.genatomic = assert(genatomic, 'genatomic')
                      	--lanes.configure = nil -- no need to call configure() ever again
                      	return lanes;
                      
                      ]]
                      
                      	--load the above lua lanes.lua to globals
                      	return assert (loadstring(s_LanesV2Lua) () , "load lua lanes failed");
                      
                      end --func
                      
                      ------------End of Lanes Lua via loadstring function -----------------------------
                      ----------------------------------------------------------------------------------
                      
                      -----load lua lanes (calls require in the lanes lua string)-----
                      
                      lanes = LanesV2x_Init(); --the function could be made local global(if local cannot be called from within a lane !))
                      
                      ----------------------------------------------------------------
                      hth

                      Comment


                      • #26
                        ^^ thanks for that

                        Comment


                        • #27
                          @Eagle [or other Lanes guru], I've been using Lanes for a while and now successfully with MemoryEx but to date all I've been doing is starting a thread and then letting it do what's needed then return some values if needed but now with MemoryEx I'm loading that in a lane along with redefining structures and reopening library's to get things to work as I want and it's getting a bit CPU intensive on a second timer so what I'm wondering is how to open a lane and keep it open while just passing a table to it with info when I need it to process stuff so I need not keep loading modules and plugins, say like so:

                          Code:
                          MyLaneFunction = function()
                          
                          --Load MemoryEx.
                          --Define structures.
                          --Load library's.
                          
                          --[[
                          
                             1: Do nothing here until the lane receives a message.
                             2: Once it's processed the message go back to 1 and wait for another message.
                          
                          --]]
                          
                          --Exit if a message is sent to exit.
                          --Return nothing.
                          
                          end

                          Comment


                          • #28
                            Code:
                            MyLaneFunction = function()
                            
                            --Load MemoryEx.
                            --Define structures.
                            --Load library's.
                            
                             while true do
                               local c = linda:receive("cmd")
                               if c == "exit" then
                                TextFile.WriteFromString(_DesktopFolder.."\\test.txt","Exit\n",true)
                                break
                               elseif c and (type(c) == "table") then
                                TextFile.WriteFromString(_DesktopFolder.."\\test.txt","Test\n",true)
                               end
                             end
                            
                            --Exit if a message is sent to exit.
                            --Return nothing.
                            
                            end
                            Code:
                            function QueryAllowProjectClose()
                              linda:send("cmd","exit")
                            end
                            On Timer:

                            Code:
                            t = {}
                            linda:send("cmd",t)
                            This is working great, it seems the while loop is non busy as it uses next to no CPU when doing nothing, think this is as close to a thread as one will get in AMS and with MemoryEX in action in the 'thread' this is a whole new level...........

                            Comment


                            • #29
                              Ya dis is good ya, suggest using linda:set and linda:get as less overhead,
                              although linda:send and receive have more options available to them if really needed.

                              will post some more stuff on this and lua lanes in the showcase section under Webultra's easylanes thread
                              as he was the one who inspired me to look into 'lanes' a bit more.

                              will also include the latest compiled version of lanes which is currently at v3.9.5.0 for educational purposes.

                              nice work Shrek keep on 'Shreking' hehe

                              Comment


                              • #30
                                ^^, linda:set and linda:get don't seem to be working with EasyLanes used with your loadstring and Lua Lanes v2.2.

                                One other thing with MemoryEx in the lane loaded as in post 28, after a while for a random reason it will error out saying 'SendMessageA not found in loaded module' and it's a bit odd given it happily sends messages to windows previously, what could be the reason for forgetting what functions have been loaded in the dll?

                                Comment

                                Working...
                                X
                                😀
                                🥰
                                🤢
                                😎
                                😡
                                👍
                                👎