Locking nodes when deleting from threaded linked list - linked-list

I'm new to pthreads and I need to safely delete nodes from a linked list that is shared by all threads. I am not completely understanding when to lock and unlock a node. This is what I have so far for removing a node that is the head. I lock the head before it is accessed (it is accessed in the while condition) but when do I unlock it?

When deleting a node, you can't just lock the node itself: because you're changing the pointer to that node, which is stored outside of the node, you need to protect that pointer from concurrent access.
In other words, you can't use head->lock to protect head, because lock is inside the node, and the pointer head itself is not. For example, you could have a lock declared alongside head called head_lock.
This also affects how your code that adds to and looks up the list works - that code needs to lock head_lock while it accesses the head pointer, too.
Whether or not you should just rely on the single head_lock to protect the entire list, or also have individual per-node locks depends on how you use the list nodes and the amount of contention there is for access to the list.

Related

reliably querying “delta since last read” in neo4j

In neo4j I have an application where an API endpoint does CRUD operations on the graph, then I materialize reachable parts of the graph starting at known nodes, and finally I send out the materialized subgraphs to a bunch of other machines that don’t know how to query neo4j directly. However, the materialized views are moderately large, and within a given minute only small parts of each one will change, so I’d like to be able to query “what has changed since last time I checked” so that I only have to send the deltas. What’s the best way to do that? I’m not sure if it helps, but my data doesn’t contain arbitrary-length paths — if needed I can explicitly write each node and edge type into my query.
One possibility I imagined was adding a “last updated” timestamp as a property on every node and edge, and instead of deleting things directly, just add a “deleted” boolean property and update the timestamp, and then use some background process to actually delete a few minutes later (after the deltas have been sent out). Then in my query, select all reachable nodes and edges and filter them based on the timestamp property. However:
If there’s clock drift between two different neo4j write servers and the Raft leader changes from one to the other, can the timestamps go back in time? Or even worse, will two concurrent writes always give me a transaction time that is in commit order, or can they be reordered within a single box? I would rather use a graph-wide monotonically-increasing integer like
the write commit ID, but I can’t find a function that gives me that.
Or theoretically I could use the cookie used for causal consistency,
but since you only get that after the transaction is complete, it’d
be messy to have to do every write as two separate transactions.
Also, it just sucks to use deletion markers because then you have to explicitly remove deleted edges / nodes in every other query you do.
Are there other better patterns here?

How stable are the neo4j IDs?

I know that you're not supposed to rely on IDs as identifier for nodes over the long term because when you delete nodes, the IDs may be re-assigned to new nodes (ref).
Neo4j reuses its internal ids when nodes and relationships are deleted. This means that applications using, and relying on internal Neo4j ids, are brittle or at risk of making mistakes. It is therefore recommended to rather use application-generated ids.
If I'm understanding this correctly, then only looking up a node/relationship by its id when you can't guarantee if it may have been deleted puts you at risk.
If through my application design I can guarantee that the node with a certain ID hasn't been deleted since the time ID was queried, am I alright to use the IDs? Or is there still some problem that I might run into?
My use case is that I wish to perform a complex operation which spans multiple transactions. And I need to know if the ID I obtained for a node during the first transaction of that operation is a valid way of identifying the node during the last transaction of the operation.
As long as you are certain that a node/relationship with a given ID won't be deleted, you can use its native ID indefinitely.
However, over time you may get want to add support for other use cases that will need to delete that entity. Once that happens, your existing query could start producing intermittent errors (that may not be obvious).
So, it is still generally advisable to use your own identification properties.

List all living nodes / actions / animations in a Cocos2D app

Is it possible to list all living nodes (actions and animations are of interest to me too) in a Cocos2D app?
Currently I am fighting memory issues in an app and even though profiler helps with that I would like to try other approaches too.
You can recursively list all child nodes. The start node will be your scene. For actions, I know that you can get number of actions for given node, but i don't know if it is possible to list all actions in some way.
Also, you may use CCTextureCache to check if all of unused textures were already removed from memory. It has no public methods to access this data, but you can see loaded textures names in debugger or add some dumping method.
To prevent memory leak by scheduling some action on node, that you want to remove from parent, send cleanup message to all of nodes before removing from parent. Or if it is instance of your class, make [self cleanup]; in it's onExit() method.
I don't think, that you can receive the list of all created nodes. It sounds like garbage collection in .net =) In objective-C you must watch for leaked objects by yourself.

MIPS32 - Deallocate memory

Suppose I have a linked list in MIPS32 and at some point I want to remove one of the nodes.
What I do it to make the predecessor node to point to the next node of the node removed.
However the removed node still contains some data. So the question is how do I find out whether that node is usable in future or not?
One suggestion was to create a second linked list containing all the nodes that are usable. However, how would I go to implement such a list? Also, do you think this list should point to all the usable space in memory or just to the one of the removed nodes?
Is there any other better way to accomplish the same result?
Solution:
Whenever we "ask" for new memory we use the sbrk service using syscall. However, if we've removed something from our data structure we may want to use that removed part of memory.
So a solution could be to have a linked list of nodes that could be re-used. Whenever we remove something from our data structure we add the part of memory (i.e. a node) to the linked list that keeps track of re-usable memory.
Therefore, when we've to add something to our data structure we first check whether there is some re-usable node in our "memory linked list". If this is not the case, we can use sbrk as usual.
Whenever we "ask" for new memory we use the sbrk service using syscall. However, if we've removed something from our data structure we may want to use that removed part of memory.
So a solution could be to have a linked list of nodes that could be re-used. Whenever we remove something from our data structure we add the part of memory (i.e. a node) to the linked list that keeps track of re-usable memory.
Therefore, when we've to add something to our data structure we first check whether there is some re-usable node in our "memory linked list". If this is not the case, we can use sbrk as usual.

How to atomatically delete specs of terminated children in a dynamic supervisor

No knowledge of USB needed for this question, just described it as it is to make the example more conrete.
I'm trying to implement a dynamic supervisor for specific devices on a USB bus.
These devices have addresses and appear and disappear during the lifetime of the system.
For each device I need a dynamic child for my supervisor.
These children are transient, so once they crash or terminate we don't restart them (because probably they are gone then).
I have a process that scans the USB port at certain times and produces a list of all addresses of the USB devices I want to handle.
I plan to call supervisor:which_children/1 before each scan to find out which devices are present but have no child process running.
In order to find out which addresses have children running I plan to create Id atoms for the childspec that contain the addresses (there are only a few addresses possible), e.g. adr_12 if the child handles address 12.
When I try to start/restart missing children I have the somewhat ugly situation that the child specs are not automatically deleted when the transient child terminates or crashes (at least I think that it is so). So I would need code like this:
case supervisor:start_child(my_sup, Spec) of
{error, already_present} ->
supervisor:restart_child(my_sup, Spec);
Any -> Any
end
Then there is the problem that I don't know if supervisor:which_children/1 also returns already terminated children.
So it would be best if children would be deleted after they transiently terminate.
Somehow all this feels inelegant to me so I'm asking myself (and you):
How can I resolve this most elegantly?
Is it better not to use a supervisor at all in this situation?
My gut feeling/knee jerk reaction is: 'You need to use a simple_one_for_one' supervisor for them, so their spec gets removed when it stops. If you need to be able to grab a specific process for communication, I would use the gproc application for that (or an ETS table).
It sounds to me like the children you want to dynamically add to your supervisor are very similar each other. Maybe a simple-one-for-one supervisor is what you need. These supervisors are "a simplified version of the one_for_one supervisor, where all child processes are dynamically added instances of the same process.". Every child will have the same child specs, so you don't need to specify it when you call the supervisor:add_child/2.
Also, mind that the above idea of creating an atom (e.g. adr_12) dynamically could be dangerous. Atoms are limited in an Erlang system (by default ~1000000). See the documentation for details.

Resources