ici::doc::pod3::smlist(3)

πŸ“¦ version 3.2.1, in ubuntu jammy

πŸ’– NAME πŸ’–

ici::doc::pod3::smlist β€” straight out of the ICI library functions manual, bestie ✨ β€” and what it's actually about is smlist, the shared memory list management library. that's the whole vibe, no cap.


✨ SYNOPSIS ✨

#include "smlist.h"

typedef int (*SmListCompareFn)
    (PsmPartition partition, PsmAddress eltData, void *argData);
typedef void (*SmListDeleteFn)
    (PsmPartition partition, PsmAddress elt, void *argument);

[see description for available functions]

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the smlist library is your girl for creating, manipulating and destroying doubly-linked lists in shared memory. πŸ’… just like lyst(3), smlist works with two kinds of objects: list objects and element objects. but here's the plot twist β€” since these objects live in shared memory that's managed by psm(3), the pointers to them get carried around as PsmAddress values. πŸŽ€

so like:

  • a list knows how many elements it contains, and what its first and last elements are. she keeps track, periodt.
  • an element knows what list it belongs to, the elements before and after it in its list, and also its content β€” which is normally the PsmAddress of some object in shared memory. main character energy fr fr.

here's the whole lineup of functions, babes:

  • PsmAddress sm_list_create(PsmPartition partition) β€” makes a brand new list object with absolutely zero elements in it, inside the memory segment identified by partition. returns the PsmAddress of the list, or 0 on any error. πŸ’–
  • void sm_list_unwedge(PsmPartition partition, PsmAddress list, int interval) β€” un-wedges, as necessary, the mutex semaphore protecting shared access to the list you pointed at. for the deets, go read the explanation of the sm_SemUnwedge() function over in platform(3). 🫢
  • int sm_list_clear(PsmPartition partition, PsmAddress list, SmListDeleteFn delete, void *argument) β€” empties a list out. frees every single element of the list. if the delete function is non-NULL, that function gets called once for each freed element, and when it's called it receives the PsmAddress of the list element plus the argument pointer you passed to sm_list_clear(). returns 0 on success, -1 on any error.
  • int sm_list_destroy(PsmPartition partition, PsmAddress list, SmListDeleteFn delete, void *argument) β€” destroys a list. same as sm_list_clear(), except it additionally frees the list structure itself. returns 0 on success, -1 on any error. πŸ’€ she's gone gone.
  • int sm_list_user_data_set(PsmPartition partition, PsmAddress list, PsmAddress userData) β€” sets the value of a user data variable that's associated with the list as a whole. you can use this value for literally anything; the classic move is storing the PsmAddress of a shared memory block holding data (state data, for example) that you want to associate with the list. returns 0 on success, -1 on any error.
  • PsmAddress sm_list_user_data(PsmPartition partition, PsmAddress list) β€” hands back the value of the user data variable associated with the list as a whole, or 0 on any error. ✨
  • int sm_list_length(PsmPartition partition, PsmAddress list) β€” returns the number of elements in the list. that's it, that's the girl.
  • PsmAddress sm_list_insert(PsmPartition partition, PsmAddress list, PsmAddress data, SmListCompareFn compare, void *dataBuffer) β€” creates a new list element whose data value is data, and inserts it into the given list. if the compare function is NULL, the new element just gets appended to the list, easy. otherwise, the new element gets inserted after the last element in the list whose data value is "less than or equal to" the data value of the new element (that's the one in dataBuffer) according to the collating sequence established by compare. returns the PsmAddress of the new element, or 0 on any error. 🌸
  • PsmAddress sm_list_insert_first(PsmPartition partition, PsmAddress list, PsmAddress data) PsmAddress sm_list_insert_last(PsmPartition partition, PsmAddress list, PsmAddress data) β€” create a new list element and insert it at the start / end of a list. returns the PsmAddress of the new element on success, or 0 on any error. heads up: this disregards any established sort order in the list. πŸ™ˆ
  • PsmAddress sm_list_insert_before(PsmPartition partition, PsmAddress elt, PsmAddress data) PsmAddress sm_list_insert_after(PsmPartition partition, PsmAddress elt, PsmAddress data) β€” create a new list element and insert it before / after a given element. returns the PsmAddress of the new element on success, or 0 on any error. again: disregards any established sort order in the list. 😭
  • int sm_list_delete(PsmPartition partition, PsmAddress elt, SmListDeleteFn delete, void *argument) β€” deletes an element from a list. if the delete function is non-NULL, that function gets called when elt is deleted, and it's passed the PsmAddress of the list element plus the argument pointer you passed to sm_list_delete(). returns 0 on success, -1 on any error.
  • PsmAddress sm_list_first(PsmPartition partition, PsmAddress list) PsmAddress sm_list_last(PsmPartition partition, PsmAddress list) β€” return the PsmAddress of the first / last element in list, or 0 on any error. πŸ’…
  • PsmAddress sm_list_next(PsmPartition partition, PsmAddress elt) PsmAddress sm_list_prev(PsmPartition partition, PsmAddress elt) β€” return the PsmAddress of the element following / preceding elt in that element's list, or 0 on any error. go for a lil stroll through the list, bestie. πŸšΆβ€β™€οΈ
  • PsmAddress sm_list_search(PsmPartition partition, PsmAddress elt, SmListCompareFn compare, void *dataBuffer) β€” searches a list for an element whose data matches the data in dataBuffer. if the compare function is non-NULL, the list is assumed to be sorted in the order that function implies, and the function gets automatically called once for each element of the list until it returns a value greater than or equal to zero (where zero means an exact match, and a value greater than zero means the list contains no matching element at all πŸ˜”). every time compare is called it receives the PsmAddress that is the element's data value, plus the dataBuffer value you passed to sm_list_search(). if compare is NULL, then the entire list gets searched until an element is found whose data value equals ((PsmAddress) dataBuffer). returns the PsmAddress of the matching element if one turns up, 0 otherwise.
  • PsmAddress sm_list_list(PsmPartition partition, PsmAddress elt) β€” returns the PsmAddress of the list that elt belongs to, or 0 on any error. found her home 🏠
  • PsmAddress sm_list_data(PsmPartition partition, PsmAddress elt) β€” returns the PsmAddress that is the data value for elt, or 0 on any error.
  • PsmAddress sm_list_data_set(PsmPartition partition, PsmAddress elt, PsmAddress data) β€” sets the data value for elt to data, replacing the original value. returns the original data value for elt, or 0 on any error. ngl, that original data value for elt may or may not have been the address of an object in memory β€” and even if it was, that object was NOT deleted. 😳
⚠️ Warning: changing the data value of an element of an ordered list may ruin the ordering of the list. like, it's giving chaos. don't do it unless you mean it. πŸ’€

🌈 USAGE 🌈

a user normally creates an element and adds it to a list like this, step by step:

  1. obtaining a shared memory block to contain the element's data;
  2. converting the shared memory block's PsmAddress to a character pointer;
  3. using that pointer to write the data into the shared memory block;
  4. calling one of the sm_list_insert functions to create the element structure (which will include the shared memory block's PsmAddress) and insert it into the list. ✨

when inserting elements or searching a list, you may optionally provide a compare function shaped like this:

int user_comp_name(PsmPartition partition, PsmAddress eltData,
                   void *dataBuffer);

when you provide it, this function gets automatically called by whichever smlist function you invoked 🫢. when it's called, it receives the content of a list element (eltData, nominally the PsmAddress of an item in shared memory) and an argument, dataBuffer, which is nominally the address in local memory of some other item in the same format. your user-supplied function normally compares some key values of the two data items and returns 0 if they're equal, an integer less than 0 if eltData's key value is less than that of dataBuffer, and an integer greater than 0 if eltData's key value is greater than that of dataBuffer. these return values produce a list in ascending order. if you want the list in descending order, the function has to reverse the signs of those return values. flip the script, literally. πŸ”„

when deleting an element or destroying a list, you may optionally provide a delete function shaped like this:

void user_delete_name(PsmPartition partition, PsmAddress elt, void *argData)

when you provide it, this function gets automatically called by whichever smlist function you invoked. when it's called, it receives the address of a list element (elt) and an argument, argData, which β€” if non-NULL β€” is normally the address in local memory of a data item providing context for the list element deletion. your user-supplied function does any application-specific cleanup associated with deleting the element, like freeing the element's content data item and/or other memory associated with the element. 🧚 clean up your mess, queen.


πŸ“ EXAMPLE πŸ“

for an example of how to use smlist, go peek at the file smlistsh.c in the utils directory of ICI. it's right there waiting for you. πŸ‘‘


πŸ’œ SEE ALSO πŸ’œ

lyst(3), platform(3), psm(3)


and that's a wrap, bestie πŸŽ€ this page was rendered by perl v5.24.1 and dated 2016-07-07 β€” a whole era, honestly. slay, go build some shared memory lists πŸ’–βœ¨

πŸ“¦ where this page comes from