How does -on_load work in erlang? - erlang

I seem to not fully understand, how the -on_load directive works. In a module i have written i have a function to initialize an ets table and populate it with some data. This function works properly when calling it explicitly. However: i thought it would be nice, if the ets table would be populated "automatically" when the module is loaded. But this does not seem to work, because ets:info(filesig) tells me "undefined" after loading the module. The relevant code looks something like:
...
-on_load(init/0),
init() ->
% load filesig database into ETS
{_, Signatures} = file:consult("path to a file"),
ets:new(filesig, [set, protected, named_table]),
ets:insert(filesig, Signatures),
ok.
...
I've tested it from within the erlang shell. Any hints for me, what i am doing wrong?

The manual says that this code runs in a newly spawned process which terminates as soon as the function returns.
The ETS table you create gets deleted once the owning process terminates. This is a standard ETS behavior. Here's what the ets man page mentions about it:
Note that there is no automatic garbage collection for tables. Even if
there are no references to a table from any process, it will not
automatically be destroyed unless the owner process terminates. It can
be destroyed explicitly by using delete/1. The default owner is the
process that created the table. Table ownership can be transferred at
process termination by using the heir option or explicitly by calling
give_away/3.

Related

Connecting a lua state to another one

I am using Lua to extend my C++ application. My application have some parts(ex: timer event, ui events) that can be extended by Lua, so for each part, I make a new state and load files and functions related to that part in it, so making a change to a part and reloading it wont affect the other parts.
Now I am in a situation that I need some general files to be shared among all other parts.
like for example : I am making a function for the timer events part, and there is a object defined in those general files i want to change its info in this function.
Now i am in the ui event part and I need when i access that object in the general file I want it to contain the changes that was made from the ui part.
So I thought about creating another state for those and like make an __index for the global table in the other state to search this state if they don't find some stuff in it:)) apparently I don't know how to make that.
I hope someone get what I mean and tell me how to make that?!
Lua states created with lua_newstate or lua_newstate are completely separated and cannot directly talk to each other: you need to copy data manually from one state to the other.
You can set an __index metamethod for the global table in one state to look for the data in the other one, but you'll have to do it in C or export a function to Lua that does that.

Setting entry point in DWScript

Is there a way to set an entry point in DWScript?
For example, if I start a script execution, I'd like it to execute a procedure Main, rather than the code in the regular entry point (begin ... end.).
I know it's possible to execute functions from Delphi, but I'm not sure this would be quite the same.
Aside from writing your procedure Main(); and then having your regular script entry point consist of nothing but calling Main, which is probably not what you're thinking of, no, there's no way to do that in DWS.
For all its innovations in syntax, DWS is still Pascal, and it still works the way Pascal works. Asking for some sort of named Main routine would be a radical departure from Pascal style.
EDIT: To answer the clarification posted in comments:
If you want your script to spawn a new script thread, you'll have to handle it in external Delphi code. As of this writing, the DWS system doesn't have any concept of multithreading built in. If you wanted to do it, you'd do something like this:
Create an external routine called something like SpawnThread(EntryPoint: string). Its eval method (out in Native-Delphi-land) would spawn a new thread that loads the current script, then finds the routine with the specified name and executes it.
That's about the only way you could get it to work without language-level support. If you'd like a way to spawn threads from within DWS, try adding it as a feature request to the issue tracker.
Calling functions directly is explicited in
https://code.google.com/p/dwscript/wiki/FirstSteps#Functions
If you want to execute a function in a different thread, you'll need some Delphi-side code to create a new thread, a new execution, and then call your functions. The main and threaded-execution will then be sandboxed from each other (so can't share share global vars etc.).
If you need to share data between the threads, you could do that by exposing functions or external variables, which would call into Delphi code with the proper synchronizations and locks in place (what is "proper" will depend on what your code wants to do, like always in multithreading...).
Note that it is possible to pass objects, interfaces and dynamic arrays between script executions (provided they're executions of the same program), but just like with regular code, you'll have to use locks, critical sections or mutexes explicitly.

How to use NIF to interact with C code that keeps state across calls (i.e., linked lists as NIF)

I wanted to create a linked-list data structure that was implemented in C. The idea was that one would create a linked list
ll:new() -> listId.
ListId, above, represents a "pointer" of some type that would get passed back to the C code which would function as some type of handle on the list. I was hoping not to have to pass the list itself back and forth since I imagined lists could get very, very large. Once the linked list was created, users would then interact with it in obvious ways:
ll:add(ListId, Elt)
ll:add_after(ListId, Pos, Elt)
I imagined I would do this via Erlang's NIF capabilities. Now, for this to work the C side has to maintain the list across multiple calls to add, add_after, etc.
In straight C, I would have a main function that a user interacts with that would keep the program alive thereby keeping the linked list persisted for the life of the user's interaction with the program. As I understand it, NIFs utilizes C code with no main function. That is, that each call to a NIF is a one-and-done type of proposition.
Can someone give me some pointers on how (assuming it is appropriate) one can utilize NIFs to interact with C code that needs keeps state across multiple calls? I hope that was clear!
Check the documentation for resource objects. The NIF API even allows you to use the erlang GC to GC the lists you create should the process which has created it crash!
the 'static' variable in C can keep value between calls, but I would strongly dont recommend this way. If you need some state, it would be better to look at 'ports' in erlang.

Registering a child in the process that initiated the start_child call

I have a logic module that tells a supervisor to start child processes. I need to store those childrens pid in the logic modules state. But I also need to update a childs pid if the supervisor restarts it.
So I can't use the return value pid from the start_child call, since that will only give me the pid on the first start, not the restarts. Right now I make the child process call a register function (updates state with new pid) in the logic module from the childs init function. That way the logic module can update the pid in its state whenever a process is restarted. The logic module is a gen_server and I'm doing a cast when i register the child process.
Can anyone see a problem with this and are there any other more "proper" way of doing it?
One problem is that you have the ChildPid and the child might be dead by now. So sending it a message through a cast will mean the message is lost. And through a call you will crash yourself with an {'EXIT', noproc} unless you catch it out of the call. Your solution must take into account that a Pid might be long gone the instant you send a message. Usually by ignoring that the message is lost, by crashing yourself, or by remedying the problem and then go on.
There are a couple of options. This is a loose list:
Do as you do. Let the childs register themselves.
Let the logic module have a monitor on the child. That way you know if it dies.
Use Erlang Solutions gproc module: https://github.com/esl/gproc which gives you a neat interface to an ETS table keeping track of the information. Note that you can look up a pid in gproc and await its arrival if the process is just restarting.
Use supervisor:which_children to find the relevant child.
Roll your own ETS table as a variant of gproc
local names have to be atoms, but globally registered names can be any term (they are stored internally in a ETS table looking somewhat like gproc's, see the global_name_server in kernel/stdlib). Use the global structure to track the pids in question.

Data persistence when worker process dies, how?

I have worker processes that needs gathered/calculated data as arguments on start up. This is then needed on re-starts as well. Where should I put the initialization code? Inside the supervisors init? Or inside the modules start_link, or init? Are there any best practices in Erlang when it comes to this?
If the gen_server component has critical state, or state which cannot be re-calculated/re-gathered, I generally avoid keeping the state in gen_server itself. I instead choose to maintain state in an external process/ets table. If you are going by this approach, make sure the ets table is either created by an externel process (which you are sure will not die), for eg., the application process -or- create the ets table in the init method of the gen_server and use the "ets:give_away/3" method to hand it off to an external process (of course, you would need to check if the table is already created in the gen_server's init method).. Else the ets table will be destroyed when the process dies..

Resources