
Liblfds, a portable, license-free, lock-free data structure library written in C - pantalaimon
http://liblfds.org/
======
misframer
Related to this is Concurrency Kit [0], which is BSD-licensed, written in C,
and provides concurrency primitives and data structures.

[0] [http://concurrencykit.org/](http://concurrencykit.org/)

~~~
liblfds
I know the author of CK, and he's very, very good. Better than me, I am sure
of that!

I believe CK offers a delete-supporting hash, too, so it has a full O(1),
which liblfds does not yet have.

~~~
pekk
While your humility is refreshing, why wouldn't people just use CK instead of
liblfds?

~~~
liblfds
The libraries are not identical; I'm not particularly up to speed with CK, I'm
not a user, but there's so much that can be done with any data structure
library that there will be things liblfds has done which CK has not, and
naturally vis-versa, such that for some one of the libraries will be a better
(or possibly the only) choice.

What those things might be I cannot much tell you, where I'm not particularly
au fait with CK.

~~~
chillacy
Might want to get acquainted then... if you've got competition for your
library and you expect users to pick you, you should know why you're better
IMO: [http://concurrencykit.org/man.html](http://concurrencykit.org/man.html)

It's free and open source but in some regards it's similar to product
design/marketing. If you don't pitch it, some reviewer on the internet will
make a stackoverflow post about it, and they won't know your strengths as well
as you do.

A blog I read recently outlined some things to figure out:
[https://blog.orangecaffeine.com/the-art-of-saying-no-
db012a2...](https://blog.orangecaffeine.com/the-art-of-saying-no-
db012a22cd28#.ejst0wc7t)

From the other comments here it sounds like some unique things you have are:

* versioned datastructures that won't change during library upgrades

* self-documenting code style

~~~
liblfds
It depends though where you're coming from.

I write the library for the pleasure of it. I'm aiming to create something _I_
think beautiful - for better or for worse, from other people's point of view
:-)

I'm not actually looking for it to be used _as such_. It may well be, if my
idea of beautiful is any good, it will come to be used, but that's... it's
like a side effect.

When you paint a picture, or sculpt a sculpture, or write a song, you're not
competing with other artists to make what other people will judge to be the
better picture, sculpture or song.

------
Sir_Cmpwn
I found this a while ago but the compatability matrix turned me away very
quickly. This is one of the least portable C libraries for data structures
I've ever seen.

~~~
benbenolson
Yeah, they refer to it as "portable", but then go on to show that they haven't
tested it on anything except x64 and ARM32; not only that, but it also depends
on what you use to compile it (kbuild, GNU make, etc.).

~~~
liblfds
That's not the case.

What you get depends only on the processor type.

What does vary is whether or not any given platform has actually been tested -
i.e. the code compiled on that platform, and the test programme run.

Currently, only ARM32, MIPS32 and x64 platforms are available, and so the test
programme has only been run on those platforms.

Finally, I think you may have been misled in the same way another reader
further down was; note that the matrix is the matrix of toolchains which are
supported _out-of-the-box_ , i.e. where the library ships with build files for
those platforms.

It is NOT the matrix of the ONLY tooclhains which can be used.

~~~
rwmj
If two people misunderstand your homepage in the same way, it may be time to
change your homepage.

~~~
liblfds
Yes (and yes).

==

(Now done).

------
nneonneo
This library claims to be license-free, but some of the modules are documented
otherwise. For example, the "Queue (bounded, many-producer, many-consumer)"
module
([http://liblfds.org/mediawiki/index.php?title=r7.1.0:Queue_%2...](http://liblfds.org/mediawiki/index.php?title=r7.1.0:Queue_%28bounded,_many_producer,_many_consumer%29))
has the following license note:

"Dmitry Vyukov granted email permission for the idea to be used and
implemented in liblfds, under the MIT license."

Similarly, the unbounded queue has an "unclear" license, rather than the
"standard liblfds" license.

It's not clear to me how the library can be license-free when one component is
very clearly MIT-licensed, and when others have no clear license status. I
would be quite cautious using this code in production or in a lawyer-sensitive
environment until the licenses are clarified.

~~~
liblfds
Good point.

When the library was initially released, back in 2009, and until recently,
it's been license-free, or at least thought to be. Recently with the addition
of Dmitry's design, and a closer analysis of the possible licensing terms, the
picture has become more nuanced - hence the inclusion of per-data structure
information regarding licensing and what happened is of course classic
computing - there's now a regression bug in the one line description of the
library! Where the "license-free" term has been in the one-line description
for so long, it was overlooked.

I have to figure out what to do about this now!

~~~
appleflaxen
It looks like you are part of the project. Can you clarify what you mean by
"license-free"?

If there literally is "no license" and something isn't public domain, then it
means you aren't authorized to use it (because the authors have a copyright,
even if they have thus far chosen not to assert it). And in order to be public
domain, it must be explicitly put there. That may be the case, but your page
would be clearer if you said so.

And if not, then a license must exist, and you should elaborate it.

~~~
liblfds
My view is that all these, ah, parameters for licensing - what is or is not,
copyright, public domain existing in some countries and not others, etc, etc -
none of these are things I have chosen. They are being imposed upon me. This
is not okay. I feel no need to go along with it all, just because other
entities force it upon me.

This is why I say license-free. It is rejection of these imposed parameters. I
know what I want here - for other people to be able to use the library as they
wish for whatever they wish, simple as that. No charges, no catches, go use
it.

However, in practise, companies and individuals must abide by all this stuff,
and so you see about the code being in the public domain, a license of your
choice being granted if you wish for one, etc. This is to address the
practical problems involved.

Regarding public domain, I think you've overlooked where it is explicitly
placed in the public domain - it's the end of a couple of sentences, so it's
understandable;

"If however for legal reasons a licence is required, the license of your
choice will be granted, and license is hereby granted up front for a range of
popular licenses : the MIT license, the BSD license, the Apache license, the
GPL and LPGL (all versions thereof) and the Creative Commons licenses (all of
them). Additionally, everything is also placed in the public domain."

~~~
el_isma
Maybe you need this license? [http://www.wtfpl.net/](http://www.wtfpl.net/)

~~~
liblfds
It's not very polite :-)

"Licensing with attitude!"

------
huhtenberg
For the lazy, a link to the latest release -
[https://github.com/liblfds/liblfds/tree/master/liblfds/liblf...](https://github.com/liblfds/liblfds/tree/master/liblfds/liblfds7.1.0/liblfds710)

PS. Code has quite a bit of that macro-heavy OpenSSL vibe to it. Definitely
not everyone's thing, but it is very readable -
[https://github.com/liblfds/liblfds/blob/master/liblfds/liblf...](https://github.com/liblfds/liblfds/blob/master/liblfds/liblfds7.1.0/liblfds710/src/lfds710_freelist/lfds710_freelist_push.c)

~~~
liblfds
Macros are heavily used to avoid making function calls.

I'd glad you find it readable - I hope you're right :-)

~~~
pantalaimon
But wouldn't a static inline achieve the same thing while keeping type-safety?

~~~
liblfds
Yes.

As I understand it, this requires either that every to-be-inlined function is
present in the public header file, so it can be #included into every user
source file which wishes to use those functions, so they turn up in the object
file and so can be inlined, _or_ we rely on the compiler and linker to inline
across object files, which is not commonly supported.

It depends upon the compiler having inlining support - the library is
targetting arbitrary compilers on bare metal platforms, so it's not
necessarily a valid assumption.

Currently, there stil remain two uses of inlining, and I am aiming to get rid
of them too in the next release. This also removes a macro from the porting
layer, making it simpler.

------
cbd1984
They say it's public domain so it is, indeed, license-free. AFAIK, the public
domain dedication makes the rest of the section chaff.

~~~
Twirrim
SQLite is public domain, but they've made licensed versions of it available
for people to buy, because:

a)public domain is a concept that is far from a world wide legally recognised
concept (its roots are in old English law)

b) public domain scares company lawyers and it's easier to give them an actual
license :D

~~~
masklinn
> public domain is a concept that is far from a world wide legally recognised
> concept

Right, the "continental" (franco-german) IP school having _moral rights_ which
the anglo-saxon IP school doesn't have[0][1].

These moral rights tend to be perpetual, non-waivable, non-assignable and
inalienable, as a result the concept of public domain in the anglo-saxon sense
doesn't really make sense, instead "public domain" is a shorthand for works
whose economic rights have lapsed (that is in fact the original meaning of the
term as coined by Alfred de Vigny) or works which don't have associated
economic rights in the first place (e.g. mathematical proofs, parliamentary
transcripts) rather than an actual legal concept, and an author can only waive
their economic rights through licensing.

[0] the english Crown Copyright has some similarities

[1] anglo-saxon copyright roughly matches the continental "economic rights"
subset of author's rights

------
bogomipz
Can someone comment on lock free data structures vs lock free algorithms. My
understanding is that there isn't as much of a symbiosis between the two as
there are with other data structures and algorithms. Is it easier to implement
a lock free data structure than a lock free algorithm?

~~~
liblfds
I may be wrong, but I think an algorithm could only be considered in terms of
locking or lock-free if multiple threads were through that algorithm
performing work on the same data at the same time (and so potentially running
into each other, in ways which would break the work being done).

I've seen server code like that - all the time of course - but the only
algorithm I can think of which has that property is a PRNG, and that can
normally be implemented on a per-thread basis, each thread holding its own
single-threaded PRNG.

This probably reflects my lack of work with algorthims. Could you give an
example?

~~~
bogomipz
I came across this recently - Treibner's algorithm, mentioned in this:

[http://people.csail.mit.edu/shanir/publications/Lock_Free.pd...](http://people.csail.mit.edu/shanir/publications/Lock_Free.pdf)

~~~
liblfds
I think you mean Treiber, right? typo with the "n".

In 1986, on an IBM mainframe, published a white paper describing how to
implement a lock-free stack (which is also a freelist, of course). It was the
first lock-free data structure. I'm not quite sure why it's being called an
algorithm!

The scalable version described in that paper is scalable by dint of adding an
elimination layer in front of the stack.

I've added such a thing, although my own design - I've not read their paper,
so I don't know how they did theirs - to the freelist in 7.1.0, but it hasn't
worked well. It roughly doubled performance on x64, when there are a large
number of cores, but reduces performance for lower numbers of cores and on
other platforms. When there are a large number of cores, performance is rock
bottom,, so doubling means going from like 1m ops/sec/core to 2m ops/sec/core,
when if you run on just one core, you'd be doing say 30mm ops/sec on that
core.

I'd expect it in principle to permit real scalability - fairly linear
performance as the number of cores rises - so I think I've missed something,
or done something wrong.

~~~
bogomipz
Oh mea culpa, yes that's a typo. I was referring to W.K Treiber and his stack
implementation. I think the fact that he referred to it as an "algorithm" is
the source of my confusion.

Is it safe to say then that distinctions such as "lock free" and "wait free"
always refer to data structures and not algorithms then?

I was curious, could you elaborate on why you think that PRNGs satisfy the
property of a lock free algorithm?

Thank you for your detailed response by the way.

~~~
liblfds
> Is it safe to say then that distinctions such as "lock free" and "wait free"
> always refer to data structures and not algorithms then?

Well, for what my thoughts are worth, I would say no, not inherently and
catagorically, but in practise, it's hard to imagine algorithms which are
multi-threaded in such a way that threads contend on shared data, such that
the design of the algorithm could even _be_ lock-free or wait-free.

Parallelized (i.e. multi-threaded) algorithms tend I think to have multiple
threads all running the same code but each being given a separate part of the
overall data to process - say an image processing algorithm, where each thread
receives an equal portion of the image to process.

A PRNG however I think _can_ (for one or two types of PRNG only, not in
general) be implemented as a lock-free algorithm. A PRNG is not a data
structure - rather, it maintains some internal state and on requests uses (and
updates) that state to generate a new random number. It is an algorithm.

The updating process must be atomic or it is compromised - you can't have one
thread half way through the state updates, and then another thread jumping in
at that point and using the half-updated internal state.

Good PRNGs hold a lot of internal state - up to a kilobytes - so it's not
possible to directly use atomic operation to update that state. However, there
is a class of PRNGs called "SplitMix" which have an 8 byte state, where on
request for a new random number, that state has a particular (quite large)
constant added to it, and the result is then passed through a hashing
function.

With this design, an atomic add can be used for the addition, and once that's
done, the requesting thread then local to itself runs the hashing function
(it's single-threaded, and merely takes an 8 byte number for input), and so
the design is lock-free - no matter how many threads are using the PRNG,
whether or not they have been idled by the OS, all other threads can still get
their work done.

This PRNG is a curiosity though - it has almost no genuine use cases. The
performance is poor when compared to the single-threaded version of the same
PRNG, and a PRNG being what it is, each thread can easily run its own, thread-
local PRNG.

~~~
bogomipz
Thanks for your detailed response. You mentioned "SplitMix" PRNGs, what is the
second one that is implemented lock free?

By the way congrats on getting your release out. This looks like good stuff.

~~~
liblfds
Make that "one" then :-)

I don't actually _know_ know of others, but I know there are a range of other
PRNGs which run on single-word states, so they _might_ be viable.

Thankyou! I see many flaws in the library though - there's so much that I can
see to improve or to add. Still, with such things, there's a lot of value in
making a release to get new functionality out so it can actually be used, even
if there's much else to be improved, or which is not as it could or should be.

------
adekok
The documentation is viewed via an embedded frame. So you can't save URLs to
the documentation. This is a known bad practice for web sites.

The API changes with every release. WTF?

 _struct lfds710_freelist_element;_

Really? Just... really? In order to use a newer version this library, you have
to change your _entire_ application for the updated function names.

And many of the lock-free structures are add-only. The binary tree is
unbalanced. Which makes it not a very good binary tree.

This looks like it was written by somone who heard "lock free", and went
"cool, I'll write a library!"

And he missed the last 40 years of software best practices.

The web site is bad, the APIs are bad, the functions aren't very useful, the
library isn't very portable, etc.

People shouldn't use this library for anything.

[edit] Updated the comment about "someone" being a 16 year-old student.

~~~
nneonneo
The library also uses some absurdly long identifiers which are bound to
clutter your code one way or another. To iterate a binary tree, use

while(lfds710_btree_au_get_by_absolute_position_and_then_by_relative_position(state,
&element, LFDS710_BTREE_AU_SMALLEST_IN_TREE,
LFDS710_BTREE_AU_INORDER_WALK_FROM_SMALLEST_TO_LARGEST))

It's not going to be possible to remember what names to use when you need to
iterate. Or, take the initialization routine. You first call

lfds710_btree_au_init_valid_on_current_logical_core( &state,
key_compare_function, LFDS710_BTREE_AU_EXISTING_KEY_FAIL, NULL );

on one core, which is perhaps reasonable, but then you call

LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE()

on other cores. That is one hell of a #define, and it's not even clear from
the name what it's doing. It seems like "LFDS710_MISC_SYNC_INITS" or something
along those lines would be clearer and easier to remember.

~~~
Sir_Cmpwn
Holy shit! That's 71 characters, which leaves you 9 characters for your code.
4 of that goes to indentation, 3 of that goes to (); and you have 2 characters
left for the parameters before you break the 80 character limit. That's
horrifying.

~~~
liblfds
OTOH, you do know exactly what it does, without having to read any docs.

I am of course open to suggestions for improvement.

~~~
mjevans
Encourage the adoption of a line-width that is longer than ancient terminals
(at least it isn't 40 cols across).

Also I'm much less concerned with absolute line width in my own code than I am
with indentation steps or number of arguments something takes without flowing
on to multiple lines.

------
cyphar
Such an odd way to license free software. It's as though the author honestly
thinks that licenses are bad for free software -- copyright has bad defaults
and licenses allow us to make free software.

~~~
liblfds
No. Property rights are absolutely, profoundly, completely, totally, utterly
central, vital, irreplacable and essential. Licenses are an offshoot of
property rights.

 _However_ , the arrangement of property rights as they are now being forced
upon me - _other entities telling me how I must go about managing my rights_
\- this I do object to.

I know what I want to do with the property rights in this case, but I am often
told there's all kinds of trouble in achieving this, because of these other
entities enforcing _their_ view of property rights upon me and the people who
would form a contract with me (by choosing to use the software on the basis I
am offering it).

~~~
cyphar
You think that the copyright default of "all works are copyrighted essentially
forever, and you cannot use, modify or share copyrighted works of any kind" is
sane? Seriously?

If you want to talk about property rights, we can talk about those. But we're
talking about copyright, which is a very different concept to property
(despite attempts to create misleading terms like "intellectual property" to
muddy the waters).

Copyright is supposed to be a method of encouraging creative works. It is not
meant to be a method for software developers to maintain control over their
users. I never said licenses were not important: YOU SAID THAT. Licenses are
incredibly important -- free software couldn't exist without them because of
draconian copyright laws funded by special interests that don't give a shit
about creative works.

~~~
liblfds
> I never said licenses were not important: YOU SAID THAT.

I thought you were saying _I_ thought licenses were not important. I was
trying to make it clear _I_ think they are fundamentally important, by being
an aspect of property rights.

~~~
cyphar
Why is the title of the submission "license-less library"? If you agree with
me that licenses are very important for free software, why even have that
section on the front page?

~~~
liblfds
Because until recently, the library was license-free.

Licenses are important _as a concept_. Licenses can exist, and when they do,
they must be honoured. They are an aspect of the property rights of the owner
of the software.

That doesn't mean you have to use one, and the library was not using one, so
it was license-free.

There might be some confusion here in that when I speak of licensing being
important, I mean the concept - I do not particularly mean licensing _as it
exists today in practise_.

As was pointed out in an early post in this discussion, the matter is now not
so clear cut. I've added per data-structure information on licensing, and it's
no so straightfoward a situation now as to be able to say, in a blanket
fashion, "license-free". I'm thinking about what to do about that. The library
is much closer to license-free than anything else, but it's hard to explain
the situation in the one-line description while keeping it short and to the
point.

~~~
cyphar
Why don't you just license it under a single free software license and call it
a day? Why say "you have an infinite set of dual licenses"? If you really,
really _really_ don't care just use CC0.

I don't understand your focus on the "concept of licensing". It's such an odd
thing to focus on with such vigour. In my mind, a license is a tool that
allows me to ensure that users of my software have freedoms that they deserve.
Some people use it as a tool for oppressing users. But licenses are a tool,
simple as that. They are a consequence of copyright law. Copyright licenses
have literally nothing to do with property rights (you can't put a copyright
license on a goat or a piece of land).

------
p0nce
Now we only need more lock-free problems :) Seriously, I'm pretty much content
with regular uncontended mutexes and atomics in the vast majority of cases.

~~~
liblfds
The lock-free binary tree on two cores is about 2x faster than the next best
method. On sixteen cores, about 20x faster.

Why not use it, if it's packaged up in a library? it's only the difference
between typing one API or another, unless there are functionality differences.

~~~
wahern
A lock-free self-balancing binary tree (e.g. RedBlack or AVL) would be
awesome. But AFAIK that's not possible using commodity hardware. In general,
there aren't many places where you can use a regular binary tree when using
externally-sourced data because it opens you up to computational complexity
attacks. You could using something like SipHash to securely randomize keys,
but then it won't be nearly as fast. And of outside of batch processing, who
uses a binary tree without deletions?

The only lock-free data structure that is practical is a queue. And that's
because a lock-free queue is really the only data structure that doesn't
require you to re-architect your entire application stack according to the
limitations of the lock-free data structure. And if you're going to re-
architect your application, better to re-architect it around message passing,
which mostly obviates the need for lock-free data structures, with queues,
again, being the obvious exception.

But it's comparatively trivial to implement a lock-free queue using
intrinsics, assuming it's a hot-spot in your application. Library dependencies
are extremely costly in terms of the long-term maintenance of software
projects. Supplying a lock-free queue in a single C file (or header) using
common compiler intrinsics, OTOH, and which automagically can be dropped into
most existing projects, might be much more useful.

~~~
liblfds
Lock-free red-black trees now existing in the literature. They were invented
recently, about two or three years ago now.

> And of outside of batch processing, who uses a binary tree without
> deletions?

IME, it's surprising how often even an add-only data structure is absolutely
fine. For example, the benchmark application uses one to store the
processor/memory topology, and perform operations upon it, such as generating
interesting combinations of cores to execute the benchmarks upon.

One other thing which helps a little is that the tree elements have a key and
a value, and the value can change at any time. So there's a bit of flexibility
there.

However, of course, the real solution is proper support for delete. The
library must have this, and it's pressing - but there's just so many other
things which also need to be done, and which have been being done. For
example, it's all very well having a tree, but without e benchmark, I have no
idea if I've implemented correctly.

Where the benchmark was added in 7.1.0, I was able to see the implementation
on ARM was utterly broken - running at about 10% of the speed of locking
trees! I investigated, fixed it, they returned to running about 3x that of the
next best solution - and that fix also gave about a 25% improvement on all
other platforms.

> The only lock-free data structure that is practical is a queue.

There's quite a few lock-free data structure in the literature. Obviously the
stack (it's ancient), then the queue (lots of variants thereof), deques, lists
(singly-linked, doubly-linked, ordered, unordered, locality aware), then
hashes (of vast importance, as they scale magnificently) and now trees.

> And that's because a lock-free queue is really the only data structure that
> doesn't require you to re-architect your entire application stack according
> to the limitations of the lock-free data structure.

What limitations do you have in mind? as far as I can see, the API for the
lock-free queue is identical to the API for the locking queue, you just get
more performance.

> But it's comparatively trivial to implement a lock-free queue using
> intrinsics

Mmm... I'm not sure I agree. The standard lock-free queue is from Michael and
Scott. It takes a while to understand it, and you have to know - really know -
all about memory ordering behaviour. I've seen more _broken_ implementations
of this data structure than working (although they work fine under low load,
of course). My original implementation made the same mistakes.

Moreover, today, although I may well be completely wrong, I think I know of
two bugs in that queue, both of which are fixed in liblfds. Getting beyond
even the white paper implementation to realising there could be issues in the
queue is another leap.

> Supplying a lock-free queue in a single C file (or > header) using common
> compiler intrinsics, OTOH, and which > automagically can be dropped into
> most existing projects, > might be much more useful.

To the extent this is true, it's true for all libraries, not just lock-free
data structure libraries. It's a question of packaging. Do you have multiple C
files and multiple header files, and compile them all up and have the user
link, or do you bundle them all together into a single file (in this case so
you have a single file per data structure, where the abstraction layers are
duplicated between them) and ship that?

That single file is going to be some hundreds of kilobyets of code.
Maintaining that arrangement would be quite painful (and error prone) for the
library developer. What you'd need in fact is to maintain the code in the form
of multiple files, and then have a release mechanism bundle them up.

In both cases, the users take your source file (or files) and add them to
their projects. In the former case, the file is added to their build files. In
the latter case, building the library is added to their build files, and then
linking also.

------
partycoder
It would be good to know more about the thread safety of the structures.

~~~
liblfds
Lock-free data structures are process, thread and interrupt safe (i.e. the
same data structure instance can be safely used across processes, threads and
both inside and outside of interrupt handlers).

~~~
partycoder
How is this guaranteed? by which process was this safety declared?

~~~
liblfds
To answer that, I need to basically explain the difference between lock-free
and locking data structures.

If we consider a locking data structure, say a binary tree using a mutex to
serialise access, we see a couple of things;

1\. when a thread holds the mutex, no other thread can get any work done

2\. if a thread holding the mutex is idled by the operating system, every
other thread cannot get any work done on the tree until that thread is finally
swapped back in

3\. if a thread is holding the mutex when an interrupt occurs, the interrupt
handler cannot use the tree, because the tree may be in an invalid state - the
mutex holding thread could be right in the middle of adjusting a bunch of
pointers

The fact that thread can be prevented from working _by other threads_ is what
is meant by saying it is a locking dats structure.

Lock-free data structures are implemented such that, broadly speaking (there
are nuances in this which are not necessary here), all threads can continue
with their work, regardless of how many other threads are using the data
structure or whether or not they've been idled by the operating system.

In short, a lock-free data structure is written in such a way that all
possible operations, and any number of them in any order can happen at ANY
time, i.e. between the execution of one instruction and the next, and the data
structure remains valid at all time.

It is this which makes the data structure process, thread and interrupt safe.

Typically, lock-free data strutures achieve this though the use atomic
operations and careful design. (Superior designs also distribute memory
accesses away from just one or a few pointers, an improvement which is
necessary but insufficient for scalability).

------
abimaelmartell
There's a different repository for every version :P

[https://github.com/liblfds?tab=repositories](https://github.com/liblfds?tab=repositories)

~~~
liblfds
Yes. The reason for this is that every version of the library can be
concurrently included and linked against. The reason for this is so that when
a new version of the library is incorporated, existing code _does not even
have to be revalidated_ , because the code _it_ is using is unchanged.

In this latest release, I've actually moved over to a single repo, which will
gain a new directory for each new release. The reason for this is that the
benchmark app builds and links against earlier version of the library, so it
can benchmark them. The gnuplots show not only the performance of locking data
strcutures running the same benchmarks, but also of the earlier versions of
liblfds.

~~~
abimaelmartell
Yeah, that doesn't sound right, if you are already using git, try to use
branches, and tags.

Also the fact that the whole API uses the version number as some kind of
namespace is weird.

~~~
liblfds
If it does not, how can you concurrently include and link against multiple
versions of the library?

~~~
wahern
On Linux and maybe Solaris you can use ELF symbol versioning.

Otherwise, if the concern is both libfoo, libbar, and bin/acme linking to
liblfds, then they should be linking it statically. Either liblfds or the
depending code (libfoo, libbar, and bin/acme) can be compiled in such a way
that liblfds symbols do not leak outside the component they're used in. On
modern systems you're not limited to static or extern linkage scopes, even
across compilation units.

Windows might be difficult. But shared, dynamically linked DLLs aren't common
on Windows. At least, not in the sense where the DLL can be sourced
independently. That's because historically DLLs were only compatible with code
compiled with the same Visual Studio release (because CRT intrinsics and data
structures were not backwards or forwards compatible), which meant that in
practice you always bundled dependencies, even if dynamically linked, to
ensure everything was compatible.

~~~
liblfds
> On Linux and maybe Solaris you can use ELF symbol versioning.

Remember that the library supports bare metal platforms. It is intended to be
used in the absence of an operating system.

I'm afraid I'm not sure I undersand what you've written.

My aim is to ensure that for applications using the library, that when a new
release comes out, that they can use it while seeing _absolutely no change in
the code they are already using_ (header files, the binary being linked to,
etc), as this is the and the only way to _know_ that existing code will be
_wholly unaffected_.

------
glibgil
Shouldn't this type of library be done in rust from now on?

~~~
monocasa
This library has been around for many years, and predates anything resembling
stable rust by more than half a decade.

~~~
liblfds
God, I'm old.

