1
0
Fork 0

Compare commits

..

No commits in common. "45f455831ceb4899ab9e4053b18b10475f40c910" and "7fd6727a6e00762a1c618b4ec9f89d0d5b739ea4" have entirely different histories.

18 changed files with 888 additions and 826 deletions

View file

@ -1,2 +0,0 @@
_release
_debug

View file

@ -9,14 +9,6 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt-get install -y make clang-format
- run: make lint
- run: git diff --exit-code
build-with-gcc: build-with-gcc:
strategy: strategy:
matrix: matrix:
@ -24,35 +16,29 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: {fetch-depth: 0}
- run: sudo apt-get install -y build-essential - run: sudo apt-get install -y build-essential
- run: make VERBOSE=1 CFG=${{ matrix.cfg}} -j$(nproc) - run: make CFG=${{ matrix.cfg}} -j$(nproc)
- run: | - run: _${{ matrix.cfg }}/inotify-info
_${{ matrix.cfg }}/inotify-info --version
_${{ matrix.cfg }}/inotify-info
build-with-zig: build-with-zig:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: {fetch-depth: 0}
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
key: zig-sdk-and-cache-${{ hashFiles('.github/workflows/ci.yaml') }} key: zig-sdk-and-cache-${{ hashFiles('.github/workflows/ci.yaml') }}
path: ~/.cache/zig path: ~/.cache/zig
- run: | - run: |
wget --progress=dot:mega \ wget --progress=dot:mega \
https://ziglang.org/download/0.13.0/zig-linux-$(uname -m)-0.13.0.tar.xz https://ziglang.org/download/0.11.0/zig-linux-$(uname -m)-0.11.0.tar.xz
tar -xJf zig-linux-*.tar.xz tar -xJf zig-linux-*.tar.xz
rm zig-linux-*.xz rm zig-linux-*.xz
mv zig-linux-* zig-sdk mv zig-linux-* zig-sdk
- run: | - run: |
make VERBOSE=1 -j$(nproc) \ make -j$(nproc) \
CC="zig-sdk/zig cc -target $(uname -m)-linux-musl" \ CC="zig-sdk/zig cc -target $(uname -m)-linux-musl" \
CXX="zig-sdk/zig c++ -target $(uname -m)-linux-musl" CXX="zig-sdk/zig c++ -target $(uname -m)-linux-musl"
- run: | - run: _release/inotify-info
_release/inotify-info --version
_release/inotify-info
build-with-docker: build-with-docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View file

@ -8,10 +8,15 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Archive
run: make inotify-info-${{ github.ref_name }}.tar.gz
- name: Release - name: Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/v') if: startsWith(github.ref, 'refs/tags/v')
with: with:
files: inotify-info-${{ github.ref_name }}.tar.gz
generate_release_notes: true generate_release_notes: true
draft: true draft: true
prerelease: true prerelease: true

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
_debug/ _debug/
_release/ _release/
/inotify-info-*.tar.gz /inotify-info-v*.tar.gz

View file

@ -1,14 +1,23 @@
FROM alpine:edge FROM alpine
RUN apk add make zig git # zig is installed from the upstream tarball, because:
# - as of writing, alpine has zig only in testing (which is cumbersome to use)
# - apk get zig pulls in libllvm, which is huge.
#
# Upstream tarball is statically linked, making it small and convenient to use.
RUN apk add make \
&& wget https://ziglang.org/download/0.11.0/zig-linux-$(uname -m)-0.11.0.tar.xz \
&& tar -xJf zig-linux-*.tar.xz \
&& rm zig-linux-*.xz \
&& mv zig-linux-* zig
WORKDIR inotify-info WORKDIR inotify-info
COPY . . COPY . .
RUN CC="zig cc -target $(uname -m)-linux-musl" \ RUN CC="/zig/zig cc -target $(uname -m)-linux-musl" \
CXX="zig c++ -target $(uname -m)-linux-musl" \ CXX="/zig/zig c++ -target $(uname -m)-linux-musl" \
make VERBOSE=1 make
FROM scratch FROM scratch
COPY --from=0 /inotify-info/_release/inotify-info /inotify-info COPY --from=0 /inotify-info/_release/inotify-info /inotify-info

View file

@ -20,16 +20,11 @@ ifeq ($(CFG), debug)
ASAN ?= 1 ASAN ?= 1
endif endif
PREFIX ?= /usr/local
BINDIR := $(PREFIX)/bin
LD = $(CC) LD = $(CC)
RM = rm -f RM = rm -f
MKDIR = mkdir -p MKDIR = mkdir -p
VERBOSE ?= 0 VERBOSE ?= 0
INOTIFYINFO_VERSION ?= $(shell git describe --tags --dirty 2>/dev/null || echo unknown)
COMPILER = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) COMPILER = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
WARNINGS = -Wall -Wextra -Wpedantic -Wmissing-include-dirs -Wformat=2 -Wshadow WARNINGS = -Wall -Wextra -Wpedantic -Wmissing-include-dirs -Wformat=2 -Wshadow
@ -38,15 +33,10 @@ ifneq ($(COMPILER),clang)
WARNINGS += -Wsuggest-attribute=format -Wall WARNINGS += -Wsuggest-attribute=format -Wall
endif endif
DEFINES = -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 CFLAGS = $(WARNINGS) -march=native -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
DEFINES += -DINOTIFYINFO_VERSION=\"$(INOTIFYINFO_VERSION)\" CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
CXXFLAGS = -fno-rtti -Woverloaded-virtual
CFLAGS += $(WARNINGS) $(DEFINES) LDFLAGS = -march=native -gdwarf-4 -g2 -Wl,--build-id=sha1
CFLAGS += -std=gnu99 -fno-exceptions
CXXFLAGS += $(WARNINGS) $(DEFINES)
CXXFLAGS += -std=c++11 -fno-exceptions -fno-rtti -Woverloaded-virtual
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++ LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
CFILES = \ CFILES = \
@ -69,7 +59,6 @@ ifeq ($(ASAN), 1)
ASAN_FLAGS += -fsanitize=object-size # enable object size checking, detect various out-of-bounds accesses. ASAN_FLAGS += -fsanitize=object-size # enable object size checking, detect various out-of-bounds accesses.
ASAN_FLAGS += -fsanitize=alignment # enable alignment checking, detect various misaligned objects; ASAN_FLAGS += -fsanitize=alignment # enable alignment checking, detect various misaligned objects;
CFLAGS += $(ASAN_FLAGS) CFLAGS += $(ASAN_FLAGS)
CXXFLAGS += $(ASAN_FLAGS)
LDFLAGS += $(ASAN_FLAGS) LDFLAGS += $(ASAN_FLAGS)
endif endif
@ -83,6 +72,7 @@ else
endif endif
PROJ = $(ODIR)/$(NAME) PROJ = $(ODIR)/$(NAME)
$(info Building $(ODIR)/$(NAME)...)
ifeq ($(VERBOSE), 1) ifeq ($(VERBOSE), 1)
VERBOSE_PREFIX= VERBOSE_PREFIX=
@ -104,16 +94,12 @@ $(ODIR)/$(NAME): $(OBJS)
$(ODIR)/%.o: %.c Makefile $(ODIR)/%.o: %.c Makefile
$(VERBOSE_PREFIX)echo "---- $< ----"; $(VERBOSE_PREFIX)echo "---- $< ----";
@$(MKDIR) $(dir $@) @$(MKDIR) $(dir $@)
$(VERBOSE_PREFIX)$(CC) -MMD -MP $(CFLAGS) -o $@ -c $< $(VERBOSE_PREFIX)$(CC) -MMD -MP -std=gnu99 $(CFLAGS) -o $@ -c $<
$(ODIR)/%.o: %.cpp Makefile $(ODIR)/%.o: %.cpp Makefile
$(VERBOSE_PREFIX)echo "---- $< ----"; $(VERBOSE_PREFIX)echo "---- $< ----";
@$(MKDIR) $(dir $@) @$(MKDIR) $(dir $@)
$(VERBOSE_PREFIX)$(CXX) -MMD -MP $(CXXFLAGS) -o $@ -c $< $(VERBOSE_PREFIX)$(CXX) -MMD -MP -std=c++11 $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
.PHONY: lint
lint:
find . -name '*.h' -o -name '*.c' -o -name '*.cpp' | xargs clang-format -i --style=webkit
.PHONY: clean .PHONY: clean
@ -124,18 +110,8 @@ clean:
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.d) $(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.d)
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.dwo) $(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.dwo)
.PHONY: install
install: all
install -D $(PROJ) $(BINDIR)/$(NAME)
.PHONY: uninstall
uninstall:
$(RM) $(BINDIR)/$(NAME)
define RELEASE_RULES define RELEASE_RULES
inotify-info-$(TAG).tar.gz: inotify-info-$(TAG).tar.gz:
git archive --prefix=inotify-info-$(TAG)/ v$(TAG) | gzip -n > $$@ git archive --prefix=inotify-info-$(TAG)/ $(TAG) | gzip -n > $$@
endef endef
$(foreach TAG,$(shell git tag 2>/dev/null | sed -n '/^v/ s/^v//p'),$(eval $(RELEASE_RULES))) $(foreach TAG,$(shell git tag 2>/dev/null),$(eval $(RELEASE_RULES)))

View file

@ -22,11 +22,17 @@ Building _debug/inotify-info...
Linking _debug/inotify-info... Linking _debug/inotify-info...
``` ```
## Install Or you can build Docker image.
The resulting executable will be at `_release/inotify-info`. You are free to ```sh
copy the resulting executable to any suitable location in your `$PATH` or run docker build . -t inotify-info
`make install` to install to `/usr/local/bin`. ```
## Install
You are free to copy the resulting executable to any suitable location in your `$PATH`.
```
cp _release/inotify-info /usr/local/bin/
```
## Run (Prints Summary) ## Run (Prints Summary)
``` ```
@ -154,16 +160,12 @@ Searching '/' for listed inodes... (8 threads)
94111468 [10304h] /home/mikesart/.cache/xfce4/xfce4-appfinder/ 94111468 [10304h] /home/mikesart/.cache/xfce4/xfce4-appfinder/
``` ```
## Run on Docker/podman ## Run on Docker
```sh ```sh
docker build . -t inotify-info
docker run --rm --privileged -v /proc:/proc inotify-info docker run --rm --privileged -v /proc:/proc inotify-info
``` ```
When running under [podman][podman] non-root mode, append `--ulimit
nofile=65535:65535` to the `podman build` command.
## Run on Nix(OS) ## Run on Nix(OS)
``` ```
@ -179,4 +181,3 @@ nix run nixpkgs#inotify-info
[problem2]: https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources [problem2]: https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources
[lfqueue]: https://github.com/Taymindis/lfqueue [lfqueue]: https://github.com/Taymindis/lfqueue
[bsd]: https://github.com/Taymindis/lfqueue/blob/master/LICENSE [bsd]: https://github.com/Taymindis/lfqueue/blob/master/LICENSE
[podman]: https://podman.io/

20
debian/changelog vendored
View file

@ -1,23 +1,3 @@
inotify-info (0.0.3-1) sid; urgency=medium
* Uploading to sid.
* Merging upstream version 0.0.3.
* Removing manual debhelper install file, not needed anymore with new
upstream version.
* Enabling non-silent output during build.
-- Daniel Baumann <daniel.baumann@progress-linux.org> Sat, 13 Jul 2024 13:02:30 +0200
inotify-info (0.0.2-1) sid; urgency=medium
* Uploading to sid.
* Merging upstream version 0.0.2.
* Removing march.patch, not needed anymore.
* Removing dwz.patch, not needed anymore.
* Setting INOTIFYINFO_VERSION to debian package version.
-- Daniel Baumann <daniel.baumann@progress-linux.org> Mon, 03 Jun 2024 22:01:31 +0200
inotify-info (0.0.1-2) sid; urgency=medium inotify-info (0.0.1-2) sid; urgency=medium
* Uploading to sid. * Uploading to sid.

2
debian/copyright vendored
View file

@ -1,7 +1,7 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: inotify-info Upstream-Name: inotify-info
Upstream-Contact: https://github.com/mikesart/inotify-info/issues Upstream-Contact: https://github.com/mikesart/inotify-info/issues
Source: https://github.com/mikesart/inotify-info/tags Source: https://github.com/mikesart/inotify-info/releases
Files: * Files: *
Copyright: 2021 Michael Sartain <mikesart@fastmail.com> Copyright: 2021 Michael Sartain <mikesart@fastmail.com>

1
debian/inotify-info.install vendored Normal file
View file

@ -0,0 +1 @@
_release/inotify-info /usr/bin

19
debian/patches/debian/0001-march.patch vendored Normal file
View file

@ -0,0 +1,19 @@
Author: Daniel Baumann <daniel.baumann@progress-linux.org>
Description: Building without -march=native (Closes: #1071076).
diff -Naurp inotify-info.orig/Makefile inotify-info/Makefile
--- inotify-info.orig/Makefile
+++ inotify-info/Makefile
@@ -33,10 +33,10 @@ ifneq ($(COMPILER),clang)
WARNINGS += -Wsuggest-attribute=format -Wall
endif
-CFLAGS = $(WARNINGS) -march=native -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
+CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
CXXFLAGS = -fno-rtti -Woverloaded-virtual
-LDFLAGS = -march=native -gdwarf-4 -g2 -Wl,--build-id=sha1
+LDFLAGS = -gdwarf-4 -g2 -Wl,--build-id=sha1
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
CFILES = \

15
debian/patches/debian/0002-dwz.patch vendored Normal file
View file

@ -0,0 +1,15 @@
Author: Daniel Baumann <daniel.baumann@progress-linux.org>
Description: Building without -gsplit-dwarf to workaround bug in dwz causing FTBFS (#1016936).
diff -Naurp inotify-info.orig/Makefile inotify-info/Makefile
--- inotify-info.orig/Makefile
+++ inotify-info/Makefile
@@ -33,7 +33,7 @@ ifneq ($(COMPILER),clang)
WARNINGS += -Wsuggest-attribute=format -Wall
endif
-CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
+CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames
CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
CXXFLAGS = -fno-rtti -Woverloaded-virtual
LDFLAGS = -gdwarf-4 -g2 -Wl,--build-id=sha1

2
debian/patches/series vendored Normal file
View file

@ -0,0 +1,2 @@
debian/0001-march.patch
debian/0002-dwz.patch

8
debian/rules vendored
View file

@ -1,15 +1,7 @@
#!/usr/bin/make -f #!/usr/bin/make -f
export INOTIFYINFO_VERSION = $(shell dpkg-parsechangelog -SVersion)
%: %:
dh ${@} dh ${@}
execute_after_dh_auto_clean: execute_after_dh_auto_clean:
rm -rf _release rm -rf _release
override_dh_auto_build:
dh_auto_build -- VERBOSE=1
override_dh_auto_install:
dh_auto_install -- PREFIX=$(CURDIR)/debian/inotify-info/usr

File diff suppressed because it is too large Load diff

View file

@ -22,38 +22,39 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#define RESET "\x1b[0m" #define RESET "\x1b[0m"
#define GRAY "\x1b[0;30m" #define GRAY "\x1b[0;30m"
#define RED "\x1b[0;31m" #define RED "\x1b[0;31m"
#define GREEN "\x1b[0;32m" #define GREEN "\x1b[0;32m"
#define YELLOW "\x1b[0;33m" #define YELLOW "\x1b[0;33m"
#define BLUE "\x1b[0;34m" #define BLUE "\x1b[0;34m"
#define MAGENTA "\x1b[0;35m" #define MAGENTA "\x1b[0;35m"
#define CYAN "\x1b[0;36m" #define CYAN "\x1b[0;36m"
#define WHITE "\x1b[0;37m" #define WHITE "\x1b[0;37m"
#define BGRAY "\x1b[1;30m" #define BGRAY "\x1b[1;30m"
#define BRED "\x1b[1;31m" #define BRED "\x1b[1;31m"
#define BGREEN "\x1b[1;32m" #define BGREEN "\x1b[1;32m"
#define BYELLOW "\x1b[1;33m" #define BYELLOW "\x1b[1;33m"
#define BBLUE "\x1b[1;34m" #define BBLUE "\x1b[1;34m"
#define BMAGENTA "\x1b[1;35m" #define BMAGENTA "\x1b[1;35m"
#define BCYAN "\x1b[1;36m" #define BCYAN "\x1b[1;36m"
#define BWHITE "\x1b[1;37m" #define BWHITE "\x1b[1;37m"
#define TO_STR(x) #x #define TO_STR( x ) #x
#define TO_STR_VALUE(x) TO_STR(x) #define TO_STR_VALUE( x ) TO_STR( x )
#define ATTRIBUTE_PRINTF(_x, _y) __attribute__((__format__(__printf__, _x, _y))) #define ATTRIBUTE_PRINTF( _x, _y ) __attribute__( ( __format__( __printf__, _x, _y ) ) )
#define GCC_DIAG_STR(s) #s #define GCC_DIAG_STR( s ) #s
#define GCC_DIAG_JOINSTR(x, y) GCC_DIAG_STR(x##y) #define GCC_DIAG_JOINSTR( x, y ) GCC_DIAG_STR( x##y )
#define GCC_DIAG_DO_PRAGMA(x) _Pragma(#x) #define GCC_DIAG_DO_PRAGMA( x ) _Pragma( #x )
#define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x) #define GCC_DIAG_PRAGMA( x ) GCC_DIAG_DO_PRAGMA( GCC diagnostic x )
#define GCC_DIAG_PUSH_OFF(x) \ #define GCC_DIAG_PUSH_OFF( x ) \
GCC_DIAG_PRAGMA(push) \ GCC_DIAG_PRAGMA( push ) \
GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W, x)) GCC_DIAG_PRAGMA( ignored GCC_DIAG_JOINSTR( -W, x ) )
#define GCC_DIAG_POP() GCC_DIAG_PRAGMA(pop) #define GCC_DIAG_POP() GCC_DIAG_PRAGMA( pop )
std::string string_formatv(const char *fmt, va_list ap) ATTRIBUTE_PRINTF(1, 0);
std::string string_format(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
std::string string_formatv(const char* fmt, va_list ap) ATTRIBUTE_PRINTF(1, 0);
std::string string_format(const char* fmt, ...) ATTRIBUTE_PRINTF(1, 2);

View file

@ -1,40 +1,40 @@
/* /*
* *
* BSD 2-Clause License * BSD 2-Clause License
* *
* Copyright (c) 2018, Taymindis Woon * Copyright (c) 2018, Taymindis Woon
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* * Redistributions of source code must retain the above copyright notice, this * * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. * list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright notice, * * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__ #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
#include <sched.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> // for usleep #include <unistd.h> // for usleep
#include <sched.h>
#define __LFQ_VAL_COMPARE_AND_SWAP __sync_val_compare_and_swap #define __LFQ_VAL_COMPARE_AND_SWAP __sync_val_compare_and_swap
#define __LFQ_BOOL_COMPARE_AND_SWAP __sync_bool_compare_and_swap #define __LFQ_BOOL_COMPARE_AND_SWAP __sync_bool_compare_and_swap
@ -48,14 +48,13 @@
#include <Windows.h> #include <Windows.h>
#include <time.h> #include <time.h>
#ifdef _WIN64 #ifdef _WIN64
inline BOOL __SYNC_BOOL_CAS(LONG64 volatile* dest, LONG64 input, LONG64 comparand) inline BOOL __SYNC_BOOL_CAS(LONG64 volatile *dest, LONG64 input, LONG64 comparand) {
{ return InterlockedCompareExchangeNoFence64(dest, input, comparand) == comparand;
return InterlockedCompareExchangeNoFence64(dest, input, comparand) == comparand;
} }
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \ #define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
InterlockedCompareExchangeNoFence64((LONG64 volatile*)dest, (LONG64)input, (LONG64)comparand) InterlockedCompareExchangeNoFence64((LONG64 volatile *)dest, (LONG64)input, (LONG64)comparand)
#define __LFQ_BOOL_COMPARE_AND_SWAP(dest, comparand, input) \ #define __LFQ_BOOL_COMPARE_AND_SWAP(dest, comparand, input) \
__SYNC_BOOL_CAS((LONG64 volatile*)dest, (LONG64)input, (LONG64)comparand) __SYNC_BOOL_CAS((LONG64 volatile *)dest, (LONG64)input, (LONG64)comparand)
#define __LFQ_FETCH_AND_ADD InterlockedExchangeAddNoFence64 #define __LFQ_FETCH_AND_ADD InterlockedExchangeAddNoFence64
#define __LFQ_ADD_AND_FETCH InterlockedAddNoFence64 #define __LFQ_ADD_AND_FETCH InterlockedAddNoFence64
#define __LFQ_SYNC_MEMORY MemoryBarrier #define __LFQ_SYNC_MEMORY MemoryBarrier
@ -64,14 +63,13 @@ inline BOOL __SYNC_BOOL_CAS(LONG64 volatile* dest, LONG64 input, LONG64 comparan
#ifndef asm #ifndef asm
#define asm __asm #define asm __asm
#endif #endif
inline BOOL __SYNC_BOOL_CAS(LONG volatile* dest, LONG input, LONG comparand) inline BOOL __SYNC_BOOL_CAS(LONG volatile *dest, LONG input, LONG comparand) {
{ return InterlockedCompareExchangeNoFence(dest, input, comparand) == comparand;
return InterlockedCompareExchangeNoFence(dest, input, comparand) == comparand;
} }
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \ #define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
InterlockedCompareExchangeNoFence((LONG volatile*)dest, (LONG)input, (LONG)comparand) InterlockedCompareExchangeNoFence((LONG volatile *)dest, (LONG)input, (LONG)comparand)
#define __LFQ_BOOL_COMPARE_AND_SWAP(dest, comparand, input) \ #define __LFQ_BOOL_COMPARE_AND_SWAP(dest, comparand, input) \
__SYNC_BOOL_CAS((LONG volatile*)dest, (LONG)input, (LONG)comparand) __SYNC_BOOL_CAS((LONG volatile *)dest, (LONG)input, (LONG)comparand)
#define __LFQ_FETCH_AND_ADD InterlockedExchangeAddNoFence #define __LFQ_FETCH_AND_ADD InterlockedExchangeAddNoFence
#define __LFQ_ADD_AND_FETCH InterlockedAddNoFence #define __LFQ_ADD_AND_FETCH InterlockedAddNoFence
#define __LFQ_SYNC_MEMORY() asm mfence #define __LFQ_SYNC_MEMORY() asm mfence
@ -87,9 +85,9 @@ inline BOOL __SYNC_BOOL_CAS(LONG volatile* dest, LONG input, LONG comparand)
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__ #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
#define lfq_time_t long #define lfq_time_t long
#define lfq_get_curr_time(_time_sec) \ #define lfq_get_curr_time(_time_sec) \
struct timeval _time_; \ struct timeval _time_; \
gettimeofday(&_time_, NULL); \ gettimeofday(&_time_, NULL); \
*_time_sec = _time_.tv_sec *_time_sec = _time_.tv_sec
#define lfq_diff_time(_etime_, _stime_) _etime_ - _stime_ #define lfq_diff_time(_etime_, _stime_) _etime_ - _stime_
#else #else
#define lfq_time_t time_t #define lfq_time_t time_t
@ -98,285 +96,281 @@ inline BOOL __SYNC_BOOL_CAS(LONG volatile* dest, LONG input, LONG comparand)
#endif #endif
struct lfqueue_cas_node_s { struct lfqueue_cas_node_s {
void* value; void * value;
struct lfqueue_cas_node_s *next, *nextfree; struct lfqueue_cas_node_s *next, *nextfree;
lfq_time_t _deactivate_tm; lfq_time_t _deactivate_tm;
}; };
// static lfqueue_cas_node_t* __lfq_assigned(lfqueue_t *); //static lfqueue_cas_node_t* __lfq_assigned(lfqueue_t *);
static void __lfq_recycle_free(lfqueue_t*, lfqueue_cas_node_t*); static void __lfq_recycle_free(lfqueue_t *, lfqueue_cas_node_t*);
static void __lfq_check_free(lfqueue_t*); static void __lfq_check_free(lfqueue_t *);
static void* _dequeue(lfqueue_t*); static void *_dequeue(lfqueue_t *);
static void* _single_dequeue(lfqueue_t*); static void *_single_dequeue(lfqueue_t *);
static int _enqueue(lfqueue_t*, void*); static int _enqueue(lfqueue_t *, void* );
static inline void* _lfqueue_malloc(__attribute__((unused)) void* pl, size_t sz) static inline void* _lfqueue_malloc(__attribute__ ((unused)) void* pl, size_t sz) {
{ return malloc(sz);
return malloc(sz);
} }
static inline void _lfqueue_free(__attribute__((unused)) void* pl, void* ptr) static inline void _lfqueue_free(__attribute__ ((unused)) void* pl, void* ptr) {
{ free(ptr);
free(ptr);
} }
static void* static void *
_dequeue(lfqueue_t* lfqueue) _dequeue(lfqueue_t *lfqueue) {
{ lfqueue_cas_node_t *head, *next;
lfqueue_cas_node_t *head, *next; void *val;
void* val;
for (;;) { for (;;) {
head = lfqueue->head; head = lfqueue->head;
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) { if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) {
next = head->next; next = head->next;
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) { if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) {
if (next == NULL) { if (next == NULL) {
val = NULL; val = NULL;
goto _done; goto _done;
} }
} else { }
if (next) { else {
val = next->value; if (next) {
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) { val = next->value;
break; if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
} break;
} else { }
val = NULL; } else {
goto _done; val = NULL;
} goto _done;
} }
} }
} }
}
__lfq_recycle_free(lfqueue, head); __lfq_recycle_free(lfqueue, head);
_done: _done:
// __asm volatile("" ::: "memory"); // __asm volatile("" ::: "memory");
__LFQ_SYNC_MEMORY(); __LFQ_SYNC_MEMORY();
__lfq_check_free(lfqueue); __lfq_check_free(lfqueue);
return val; return val;
} }
static void* static void *
_single_dequeue(lfqueue_t* lfqueue) _single_dequeue(lfqueue_t *lfqueue) {
{ lfqueue_cas_node_t *head, *next;
lfqueue_cas_node_t *head, *next; void *val;
void* val;
for (;;) { for (;;) {
head = lfqueue->head; head = lfqueue->head;
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) { if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, head)) {
next = head->next; next = head->next;
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) { if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, head, head)) {
if (next == NULL) { if (next == NULL) {
return NULL; return NULL;
} }
} else { }
if (next) { else {
val = next->value; if (next) {
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) { val = next->value;
lfqueue->_free(lfqueue->pl, head); if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
break; lfqueue->_free(lfqueue->pl, head);
} break;
} else { }
return NULL; } else {
} return NULL;
} }
} }
} }
return val; }
return val;
} }
static int static int
_enqueue(lfqueue_t* lfqueue, void* value) _enqueue(lfqueue_t *lfqueue, void* value) {
{ lfqueue_cas_node_t *tail, *node;
lfqueue_cas_node_t *tail, *node; node = (lfqueue_cas_node_t*) lfqueue->_malloc(lfqueue->pl, sizeof(lfqueue_cas_node_t));
node = (lfqueue_cas_node_t*)lfqueue->_malloc(lfqueue->pl, sizeof(lfqueue_cas_node_t)); if (node == NULL) {
if (node == NULL) { perror("malloc");
perror("malloc"); return errno;
return errno; }
} node->value = value;
node->value = value; node->next = NULL;
node->next = NULL; node->nextfree = NULL;
node->nextfree = NULL; for (;;) {
for (;;) { __LFQ_SYNC_MEMORY();
__LFQ_SYNC_MEMORY(); tail = lfqueue->tail;
tail = lfqueue->tail; if (__LFQ_BOOL_COMPARE_AND_SWAP(&tail->next, NULL, node)) {
if (__LFQ_BOOL_COMPARE_AND_SWAP(&tail->next, NULL, node)) { // compulsory swap as tail->next is no NULL anymore, it has fenced on other thread
// compulsory swap as tail->next is no NULL anymore, it has fenced on other thread __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, tail, node);
__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->tail, tail, node); __lfq_check_free(lfqueue);
__lfq_check_free(lfqueue); return 0;
return 0; }
} }
}
/*It never be here*/ /*It never be here*/
return -1; return -1;
} }
static void static void
__lfq_recycle_free(lfqueue_t* lfqueue, lfqueue_cas_node_t* freenode) __lfq_recycle_free(lfqueue_t *lfqueue, lfqueue_cas_node_t* freenode) {
{ lfqueue_cas_node_t *freed;
lfqueue_cas_node_t* freed; do {
do { freed = lfqueue->move_free;
freed = lfqueue->move_free; } while (!__LFQ_BOOL_COMPARE_AND_SWAP(&freed->nextfree, NULL, freenode) );
} while (!__LFQ_BOOL_COMPARE_AND_SWAP(&freed->nextfree, NULL, freenode));
lfq_get_curr_time(&freenode->_deactivate_tm); lfq_get_curr_time(&freenode->_deactivate_tm);
__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->move_free, freed, freenode); __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->move_free, freed, freenode);
} }
static void static void
__lfq_check_free(lfqueue_t* lfqueue) __lfq_check_free(lfqueue_t *lfqueue) {
{ lfq_time_t curr_time;
lfq_time_t curr_time; if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 0, 1)) {
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 0, 1)) { lfq_get_curr_time(&curr_time);
lfq_get_curr_time(&curr_time); lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree;
lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree; while ( rtfree && (rtfree != lfqueue->move_free) ) {
while (rtfree && (rtfree != lfqueue->move_free)) { nextfree = rtfree->nextfree;
nextfree = rtfree->nextfree; if ( lfq_diff_time(curr_time, rtfree->_deactivate_tm) > 2) {
if (lfq_diff_time(curr_time, rtfree->_deactivate_tm) > 2) { // printf("%p\n", rtfree);
// printf("%p\n", rtfree); lfqueue->_free(lfqueue->pl, rtfree);
lfqueue->_free(lfqueue->pl, rtfree); rtfree = nextfree;
rtfree = nextfree; } else {
} else { break;
break; }
} }
} lfqueue->root_free = rtfree;
lfqueue->root_free = rtfree; __LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 1, 0);
__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 1, 0); }
} __LFQ_SYNC_MEMORY();
__LFQ_SYNC_MEMORY();
} }
int lfqueue_init(lfqueue_t* lfqueue) int
{ lfqueue_init(lfqueue_t *lfqueue) {
return lfqueue_init_mf(lfqueue, NULL, _lfqueue_malloc, _lfqueue_free); return lfqueue_init_mf(lfqueue, NULL, _lfqueue_malloc, _lfqueue_free);
} }
int lfqueue_init_mf(lfqueue_t* lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free) int
{ lfqueue_init_mf(lfqueue_t *lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free) {
lfqueue->_malloc = lfqueue_malloc; lfqueue->_malloc = lfqueue_malloc;
lfqueue->_free = lfqueue_free; lfqueue->_free = lfqueue_free;
lfqueue->pl = pl; lfqueue->pl = pl;
lfqueue_cas_node_t* base = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t)); lfqueue_cas_node_t *base = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t));
lfqueue_cas_node_t* freebase = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t)); lfqueue_cas_node_t *freebase = lfqueue_malloc(pl, sizeof(lfqueue_cas_node_t));
if (base == NULL || freebase == NULL) { if (base == NULL || freebase == NULL) {
perror("malloc"); perror("malloc");
return errno; return errno;
} }
base->value = NULL; base->value = NULL;
base->next = NULL; base->next = NULL;
base->nextfree = NULL; base->nextfree = NULL;
base->_deactivate_tm = 0; base->_deactivate_tm = 0;
freebase->value = NULL; freebase->value = NULL;
freebase->next = NULL; freebase->next = NULL;
freebase->nextfree = NULL; freebase->nextfree = NULL;
freebase->_deactivate_tm = 0; freebase->_deactivate_tm = 0;
lfqueue->head = lfqueue->tail = base; // Not yet to be free for first node only lfqueue->head = lfqueue->tail = base; // Not yet to be free for first node only
lfqueue->root_free = lfqueue->move_free = freebase; // Not yet to be free for first node only lfqueue->root_free = lfqueue->move_free = freebase; // Not yet to be free for first node only
lfqueue->size = 0; lfqueue->size = 0;
lfqueue->in_free_mode = 0; lfqueue->in_free_mode = 0;
return 0; return 0;
} }
void lfqueue_destroy(lfqueue_t* lfqueue) void
{ lfqueue_destroy(lfqueue_t *lfqueue) {
void* p; void* p;
while ((p = lfqueue_deq(lfqueue))) { while ((p = lfqueue_deq(lfqueue))) {
lfqueue->_free(lfqueue->pl, p); lfqueue->_free(lfqueue->pl, p);
} }
// Clear the recycle chain nodes // Clear the recycle chain nodes
lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree; lfqueue_cas_node_t *rtfree = lfqueue->root_free, *nextfree;
while (rtfree && (rtfree != lfqueue->move_free)) { while (rtfree && (rtfree != lfqueue->move_free) ) {
nextfree = rtfree->nextfree; nextfree = rtfree->nextfree;
lfqueue->_free(lfqueue->pl, rtfree); lfqueue->_free(lfqueue->pl, rtfree);
rtfree = nextfree; rtfree = nextfree;
} }
if (rtfree) { if (rtfree) {
lfqueue->_free(lfqueue->pl, rtfree); lfqueue->_free(lfqueue->pl, rtfree);
} }
lfqueue->_free(lfqueue->pl, lfqueue->tail); // Last free lfqueue->_free(lfqueue->pl, lfqueue->tail); // Last free
lfqueue->size = 0; lfqueue->size = 0;
} }
int lfqueue_enq(lfqueue_t* lfqueue, void* value) int
{ lfqueue_enq(lfqueue_t *lfqueue, void *value) {
if (_enqueue(lfqueue, value)) { if (_enqueue(lfqueue, value)) {
return -1; return -1;
} }
__LFQ_ADD_AND_FETCH(&lfqueue->size, 1); __LFQ_ADD_AND_FETCH(&lfqueue->size, 1);
return 0; return 0;
} }
void* lfqueue_deq(lfqueue_t* lfqueue) void*
{ lfqueue_deq(lfqueue_t *lfqueue) {
void* v; void *v;
if ( //__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) && if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
(v = _dequeue(lfqueue))) { (v = _dequeue(lfqueue))
) {
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1); __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
return v; return v;
} }
return NULL; return NULL;
} }
void* lfqueue_deq_must(lfqueue_t* lfqueue) void*
{ lfqueue_deq_must(lfqueue_t *lfqueue) {
void* v; void *v;
while (!(v = _dequeue(lfqueue))) { while ( !(v = _dequeue(lfqueue)) ) {
// Rest the thread for other thread, to avoid keep looping force // Rest the thread for other thread, to avoid keep looping force
lfqueue_sleep(1); lfqueue_sleep(1);
} }
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1); __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
return v; return v;
} }
/**This is only applicable when only single thread consume only**/ /**This is only applicable when only single thread consume only**/
void* lfqueue_single_deq(lfqueue_t* lfqueue) void*
{ lfqueue_single_deq(lfqueue_t *lfqueue) {
void* v; void *v;
if ( //__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) && if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
(v = _single_dequeue(lfqueue))) { (v = _single_dequeue(lfqueue))
) {
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1); __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
return v; return v;
} }
return NULL; return NULL;
} }
/**This is only applicable when only single thread consume only**/ /**This is only applicable when only single thread consume only**/
void* lfqueue_single_deq_must(lfqueue_t* lfqueue) void*
{ lfqueue_single_deq_must(lfqueue_t *lfqueue) {
void* v; void *v;
while (!(v = _single_dequeue(lfqueue))) { while ( !(v = _single_dequeue(lfqueue)) ) {
// Rest the thread for other thread, to avoid keep looping force // Rest the thread for other thread, to avoid keep looping force
lfqueue_sleep(1); lfqueue_sleep(1);
} }
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1); __LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
return v; return v;
} }
size_t size_t
lfqueue_size(lfqueue_t* lfqueue) lfqueue_size(lfqueue_t *lfqueue) {
{ return __LFQ_ADD_AND_FETCH(&lfqueue->size, 0);
return __LFQ_ADD_AND_FETCH(&lfqueue->size, 0);
} }
void lfqueue_sleep(unsigned int milisec) void
{ lfqueue_sleep(unsigned int milisec) {
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__ #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration" #pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
usleep(milisec * 1000); usleep(milisec * 1000);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#else #else
Sleep(milisec); Sleep(milisec);
#endif #endif
} }

View file

@ -1,38 +1,38 @@
/* /*
* *
* BSD 2-Clause License * BSD 2-Clause License
* *
* Copyright (c) 2018, Taymindis Woon * Copyright (c) 2018, Taymindis Woon
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* * Redistributions of source code must retain the above copyright notice, this * * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. * list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright notice, * * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
#ifndef LFQUEUE_H #ifndef LFQUEUE_H
#define LFQUEUE_H #define LFQUEUE_H
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -53,30 +53,32 @@ typedef void (*lfqueue_free_fn)(void*, void*);
#endif #endif
typedef struct { typedef struct {
lfqueue_cas_node_t *head, *tail, *root_free, *move_free; lfqueue_cas_node_t *head, *tail, *root_free, *move_free;
volatile size_t size; volatile size_t size;
volatile lfq_bool_t in_free_mode; volatile lfq_bool_t in_free_mode;
lfqueue_malloc_fn _malloc; lfqueue_malloc_fn _malloc;
lfqueue_free_fn _free; lfqueue_free_fn _free;
void* pl; void *pl;
} lfqueue_t; } lfqueue_t;
extern int lfqueue_init(lfqueue_t* lfqueue); extern int lfqueue_init(lfqueue_t *lfqueue);
extern int lfqueue_init_mf(lfqueue_t* lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free); extern int lfqueue_init_mf(lfqueue_t *lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free);
extern int lfqueue_enq(lfqueue_t* lfqueue, void* value); extern int lfqueue_enq(lfqueue_t *lfqueue, void *value);
extern void* lfqueue_deq(lfqueue_t* lfqueue); extern void* lfqueue_deq(lfqueue_t *lfqueue);
extern void* lfqueue_single_deq(lfqueue_t* lfqueue); extern void* lfqueue_single_deq(lfqueue_t *lfqueue);
/** loop until value been dequeue, it sleeps 1ms if not found to reduce cpu high usage **/ /** loop until value been dequeue, it sleeps 1ms if not found to reduce cpu high usage **/
extern void* lfqueue_deq_must(lfqueue_t* lfqueue); extern void* lfqueue_deq_must(lfqueue_t *lfqueue);
extern void* lfqueue_single_deq_must(lfqueue_t* lfqueue); extern void* lfqueue_single_deq_must(lfqueue_t *lfqueue);
extern void lfqueue_destroy(lfqueue_t* lfqueue); extern void lfqueue_destroy(lfqueue_t *lfqueue);
extern size_t lfqueue_size(lfqueue_t* lfqueue); extern size_t lfqueue_size(lfqueue_t *lfqueue);
extern void lfqueue_sleep(unsigned int milisec); extern void lfqueue_sleep(unsigned int milisec);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif