From 8669462c8c1c62de0869bc8472ab46faa9ad1fe7 Mon Sep 17 00:00:00 2001 From: lexborisov Date: Thu, 9 Mar 2017 23:47:39 +0300 Subject: [PATCH] Refactoring Threads and Makefile --- Makefile | 205 ++- Makefile.cfg | 69 + include/modest/declaration.h | 8 +- include/modest/finder/finder.h | 4 +- include/modest/finder/match.h | 4 +- include/modest/finder/myosi.h | 8 +- include/modest/finder/pseudo_class.h | 4 +- include/modest/finder/thread.h | 18 +- include/modest/finder/type.h | 14 +- include/modest/glue.h | 4 +- include/modest/layer/layer.h | 4 +- include/modest/modest.h | 12 +- include/modest/myosi.h | 4 +- include/modest/node/node.h | 10 +- include/modest/node/property.h | 2 +- include/modest/node/raw_property.h | 2 +- include/modest/node/serialization.h | 10 +- include/modest/render/begin.h | 6 +- include/modest/render/binding.h | 14 +- include/modest/render/tree.h | 6 +- include/modest/render/tree_node.h | 8 +- include/modest/style/default.h | 4 +- include/modest/style/default_resources.h | 2 +- include/modest/style/map.h | 8 +- include/modest/style/raw.h | 6 +- include/modest/style/sheet.h | 6 +- include/modest/style/type.h | 8 +- include/mycore/incoming.h | 4 +- include/mycore/myosi.h | 48 +- include/mycore/mystring.h | 6 +- include/mycore/mythread.h | 159 +++ include/mycore/thread.h | 223 ---- include/mycore/thread_queue.h | 110 ++ include/mycore/utils.h | 2 +- include/mycore/utils/avl_tree.h | 4 +- include/mycore/utils/mchar_async.h | 14 +- include/mycore/utils/mcobject.h | 2 +- include/mycore/utils/mcobject_async.h | 4 +- include/mycore/utils/mcsimple.h | 2 +- include/mycore/utils/mcsync.h | 72 +- include/mycore/utils/mctree.h | 4 +- include/mycore/utils/mhash.h | 4 +- include/mycss/an_plus_b.h | 4 +- include/mycss/check.h | 6 +- include/mycss/convert.h | 6 +- include/mycss/declaration/default.h | 4 +- include/mycss/declaration/default_resources.h | 2 +- include/mycss/declaration/entry.h | 8 +- include/mycss/declaration/entry_destroy.h | 6 +- include/mycss/declaration/init.h | 4 +- include/mycss/declaration/myosi.h | 10 +- include/mycss/declaration/parser.h | 6 +- include/mycss/declaration/serialization.h | 8 +- include/mycss/declaration/state.h | 4 +- include/mycss/entry.h | 32 +- include/mycss/media/init.h | 2 +- include/mycss/media/myosi.h | 2 +- include/mycss/media/state.h | 4 +- include/mycss/mycss.h | 14 +- include/mycss/myosi.h | 2 +- include/mycss/mystring.h | 8 +- include/mycss/namespace/init.h | 6 +- include/mycss/namespace/myosi.h | 8 +- include/mycss/namespace/parser.h | 8 +- include/mycss/namespace/serialization.h | 4 +- include/mycss/namespace/state.h | 8 +- include/mycss/parser.h | 20 +- include/mycss/property/init.h | 8 +- include/mycss/property/myosi.h | 4 +- include/mycss/property/parser.h | 10 +- include/mycss/property/serialization.h | 6 +- include/mycss/property/shared.h | 12 +- include/mycss/selectors/function.h | 6 +- include/mycss/selectors/function_parser.h | 4 +- include/mycss/selectors/init.h | 6 +- include/mycss/selectors/list.h | 6 +- include/mycss/selectors/myosi.h | 10 +- include/mycss/selectors/parser.h | 14 +- include/mycss/selectors/pseudo.h | 4 +- include/mycss/selectors/serialization.h | 6 +- include/mycss/selectors/state.h | 8 +- include/mycss/selectors/value.h | 6 +- include/mycss/selectors/value_resource.h | 2 +- include/mycss/stack.h | 2 +- include/mycss/stylesheet.h | 10 +- include/mycss/tokenizer.h | 14 +- include/mycss/tokenizer_end.h | 6 +- include/mycss/tokenizer_global.h | 8 +- include/mycss/values/color.h | 8 +- include/mycss/values/color_parser.h | 6 +- include/mycss/values/consume.h | 8 +- include/mycss/values/destroy.h | 4 +- include/mycss/values/image.h | 6 +- include/mycss/values/serialization.h | 6 +- include/mycss/values/units.h | 4 +- include/mycss/values/values.h | 14 +- include/myencoding/detect_resource.h | 2 +- include/myencoding/encoding.h | 6 +- include/myencoding/myosi.h | 2 +- include/myencoding/mystring.h | 8 +- include/myencoding/resource.h | 2 +- include/myfont/cmap.h | 4 +- include/myfont/glyf.h | 4 +- include/myfont/head.h | 4 +- include/myfont/hhea.h | 4 +- include/myfont/hmtx.h | 4 +- include/myfont/loca.h | 4 +- include/myfont/maxp.h | 4 +- include/myfont/myfont.h | 28 +- include/myfont/myosi.h | 2 +- include/myfont/name.h | 4 +- include/myfont/os_2.h | 4 +- include/myfont/pclt.h | 4 +- include/myfont/vhea.h | 4 +- include/myfont/vmtx.h | 4 +- include/myhtml/api.h | 3 +- include/myhtml/callback.h | 4 +- include/myhtml/charef.h | 2 +- include/myhtml/data_process.h | 6 +- include/myhtml/myhtml.h | 51 +- include/myhtml/mynamespace.h | 4 +- include/myhtml/myosi.h | 2 +- include/myhtml/mystring.h | 10 +- include/myhtml/parser.h | 12 +- include/myhtml/rules.h | 6 +- include/myhtml/serialization.h | 6 +- include/myhtml/stream.h | 4 +- include/myhtml/tag.h | 20 +- include/myhtml/token.h | 18 +- include/myhtml/tokenizer.h | 16 +- include/myhtml/tokenizer_doctype.h | 6 +- include/myhtml/tokenizer_end.h | 6 +- include/myhtml/tokenizer_script.h | 8 +- include/myhtml/tree.h | 26 +- include/myunicode/myosi.h | 35 + include/myurl/host.h | 8 +- include/myurl/myosi.h | 2 +- include/myurl/parser.h | 4 +- include/myurl/path.h | 8 +- include/myurl/punycode.h | 6 +- include/myurl/scheme.h | 6 +- include/myurl/serialization.h | 4 +- include/myurl/url.h | 14 +- include/myurl/utils.h | 6 +- source/modest/Makefile.mk | 18 +- source/modest/finder/match.c | 31 +- source/modest/finder/thread.c | 50 +- source/modest/finder/thread.h | 2 +- source/modest/modest.c | 10 +- source/mycore/Makefile.mk | 18 +- source/mycore/myosi.c | 7 - source/mycore/myosi.h | 48 +- source/mycore/mythread.c | 335 +++++ source/mycore/mythread.h | 159 +++ source/mycore/thread.c | 1185 ----------------- source/mycore/thread.h | 223 ---- source/mycore/thread_queue.c | 650 +++++++++ source/mycore/thread_queue.h | 110 ++ source/mycore/utils/mchar_async.c | 107 +- source/mycore/utils/mchar_async.h | 10 +- source/mycore/utils/mcobject_async.c | 9 +- source/mycore/utils/mcsync.c | 131 +- source/mycore/utils/mcsync.h | 72 +- source/mycore/utils/mctree.c | 8 + source/mycore/utils/mhash.c | 12 +- source/mycss/Makefile.mk | 16 +- source/mycss/entry.c | 22 +- source/mycss/mycss.h | 4 +- source/myencoding/Makefile.mk | 16 +- source/myfont/Makefile.mk | 18 +- source/myfont/myfont.c | 15 +- source/myhtml/Makefile.mk | 16 +- source/myhtml/api.h | 3 +- source/myhtml/myhtml.c | 193 ++- source/myhtml/myhtml.h | 23 +- source/myhtml/parser.c | 10 +- source/myhtml/rules.c | 49 +- source/myhtml/tag.c | 16 +- source/myhtml/token.c | 25 +- source/myhtml/token.h | 2 +- source/myhtml/tokenizer.c | 42 +- source/myhtml/tokenizer.h | 2 +- source/myhtml/tree.c | 96 +- source/myhtml/tree.h | 8 +- source/myport/posix/Makefile.mk | 9 + source/myport/posix/mycore/io.c | 91 ++ source/myport/posix/mycore/memory.c | 42 + source/{ => myport/posix}/mycore/perf.c | 0 source/myport/posix/mycore/thread.c | 156 +++ source/myport/posix/mycore/utils/mcsync.c | 154 +++ source/myport/windows/mycore/io.c | 91 ++ source/{ => myport/windows}/mycore/memory.c | 0 source/myport/windows/mycore/perf.c | 288 ++++ source/myport/windows/mycore/thread.c | 109 ++ source/myport/windows/mycore/utils/mcsync.c | 144 ++ source/myunicode/Makefile.mk | 10 + source/myunicode/myosi.c | 7 +- source/myurl/Makefile.mk | 18 +- 198 files changed, 4046 insertions(+), 2747 deletions(-) create mode 100644 Makefile.cfg create mode 100644 include/mycore/mythread.h delete mode 100644 include/mycore/thread.h create mode 100644 include/mycore/thread_queue.h create mode 100644 include/myunicode/myosi.h create mode 100644 source/mycore/mythread.c create mode 100644 source/mycore/mythread.h delete mode 100644 source/mycore/thread.c delete mode 100644 source/mycore/thread.h create mode 100644 source/mycore/thread_queue.c create mode 100644 source/mycore/thread_queue.h create mode 100644 source/myport/posix/Makefile.mk create mode 100644 source/myport/posix/mycore/io.c create mode 100644 source/myport/posix/mycore/memory.c rename source/{ => myport/posix}/mycore/perf.c (100%) create mode 100644 source/myport/posix/mycore/thread.c create mode 100644 source/myport/posix/mycore/utils/mcsync.c create mode 100644 source/myport/windows/mycore/io.c rename source/{ => myport/windows}/mycore/memory.c (100%) create mode 100644 source/myport/windows/mycore/perf.c create mode 100644 source/myport/windows/mycore/thread.c create mode 100644 source/myport/windows/mycore/utils/mcsync.c create mode 100644 source/myunicode/Makefile.mk diff --git a/Makefile b/Makefile index 876467d..b84fd78 100644 --- a/Makefile +++ b/Makefile @@ -1,94 +1,159 @@ TARGET := source SRCDIR := source -TSTDIR := test CC ?= gcc -LIBNAME := modest -LIBPOSTFIX := .so -LIBSTATIC_POSTFIX := _static -IMP_FLAG := -LIB_TMP := lib -INCLUDE_TMP := include -BIN_TMP := bin +# ARGS +# +# MODEST_OPTIMIZATION_LEVEL, default -O2 +# MODEST_BUILD_WITHOUT_THREADS, YES or (NO or undefined), default undefined +# MODEST_BUILD_DEBUG, default undefined +# +.DEFAULT_GOAL := all + +#******************** +# Flags +#*************** MODEST_OPTIMIZATION_LEVEL ?= -O2 -CFLAGS ?= -Wall -Werror -CFLAGS += $(MODEST_OPTIMIZATION_LEVEL) -Wno-unused-variable --std=c99 -I$(SRCDIR) +MODEST_CFLAGS ?= -Wall -Werror +MODEST_CFLAGS += $(MODEST_OPTIMIZATION_LEVEL) -Wno-unused-variable --std=c99 -I$(SRCDIR) -ifneq ($(OS),Windows_NT) - CFLAGS += -fPIC -endif +MODEST_LFLAGS ?= -ifdef MODEST_BUILD_DEBUG - CFLAGS += -g -endif +#******************** +# Include +#*************** +# include dirs +INCLUDE_DIR := $(TARGET) +INCLUDE_DIR_API := include -MODEST_BUILD_WITHOUT_THREADS ?= NO -ifeq ($(MODEST_BUILD_WITHOUT_THREADS),YES) - $(info Build without POSIX Threads) - CFLAGS += -DMODEST_BUILD_WITHOUT_THREADS -DMyHTML_BUILD_WITHOUT_THREADS -else - $(info Build with POSIX Threads) - CFLAGS += -pthread -endif +#******************** +# Libraries +#*************** +# lib name +LIB_NAME := modest +LIB_NAME_SUFFIX := .so +LIB_NAME_SUFFIX_STATIC := _static.a -ifeq ($(OS),Windows_NT) - LIBPOSTFIX := .dll - IMP_FLAG := -Wl,--out-implib,$(LIB_TMP)/lib$(LIBNAME).dll.a -else - UNAM := $(shell uname -s) - ifeq ($(UNAM),Darwin) - LIBPOSTFIX := .dylib - else - CFLAGS += -D_POSIX_C_SOURCE=199309L - endif -endif +# lib dirs +LIB_DIR_BASE := lib -SRCS := -HDRS := -EXTDIRS := examples test +#******************** +# Binaries +#*************** +# binaries dirs +BIN_DIR_BASE := bin -all: create shared static - for f in $(EXTDIRS); do $(MAKE) -C $$f all; done +IMP_FLAG := +BIN_TMP := bin -include $(TARGET)/mycore/Makefile.mk -include $(TARGET)/myencoding/Makefile.mk -include $(TARGET)/myhtml/Makefile.mk -include $(TARGET)/mycss/Makefile.mk -include $(TARGET)/myfont/Makefile.mk -include $(TARGET)/myurl/Makefile.mk -include $(TARGET)/modest/Makefile.mk +#******************** +# other Makefile +#*************** +include Makefile.cfg -OBJS := $(patsubst %.c,%.o,$(SRCS)) +#******************** +# Build +#*************** +MODEST_BUILD_MODULES ?= $(dir $(wildcard $(SRCDIR)/*/)) +MODEST_BUILD_MODULES := $(patsubst %myport/,%myport/$(strip $(MODEST_PORT_NAME))/,$(MODEST_BUILD_MODULES)) +MODEST_BUILD_MODULES_LIST := $(foreach dir,$(MODEST_BUILD_MODULES),$(word 2, $(subst $(MODEST_DIR_SEPARATOR), , $(dir))) ) +MODEST_BUILD_MODULES_MAKEFILES_LIST := $(foreach dir,$(MODEST_BUILD_MODULES),$(dir)Makefile.mk) -shared: $(OBJS) - $(CC) -shared $(IMP_FLAG) $(LDFLAGS) $(OBJS) -o $(LIB_TMP)/lib$(LIBNAME)$(LIBPOSTFIX) +#******************** +# Targets +#*************** +MODEST_BUILD_MODULES_TARGET := $(MODEST_BUILD_MODULES_LIST) +MODEST_BUILD_MODULES_TARGET_ALL := $(foreach dir,$(MODEST_BUILD_MODULES_TARGET),$(dir)_all) +MODEST_BUILD_MODULES_TARGET_CLEAN := $(foreach dir,$(MODEST_BUILD_MODULES_TARGET),$(dir)_clean) +MODEST_BUILD_MODULES_TARGET_CLONE := $(foreach dir,$(MODEST_BUILD_MODULES_TARGET),$(dir)_clone) -static: shared - $(AR) crus $(LIB_TMP)/lib$(LIBNAME)$(LIBSTATIC_POSTFIX).a $(OBJS) +#******************** +# Utils +#*************** +define MODEST_UTILS_NEW_LINE -create: - mkdir -p lib bin -clean: - for f in $(EXTDIRS); do $(MAKE) -C $$f clean; done - rm -f $(OBJS) - rm -f $(LIB_TMP)/* - rm -f $(BIN_TMP)/* +endef +MODEST_UTILS_HDRS = $(foreach dir,$2,$(wildcard $(SRCDIR)/$1/$(dir)/*.h)) +MODEST_UTILS_OBJS = $(patsubst %.c,%.o,$(foreach dir,$2,$(wildcard $(SRCDIR)/$1/$(dir)/*.c))) +MODEST_UTILS_HDRS_CLONE_CMND = $(foreach path,$(foreach dir,$2,$(wildcard $(SRCDIR)/$1/$(dir)/*.h)), cp $(path) $(patsubst $(SRCDIR)%,$(INCLUDE_DIR_API)%,$(path)) $(MODEST_UTILS_NEW_LINE)) +MODEST_UTILS_HDRS_CLONE_GDIR = $(foreach dir,$2,$(INCLUDE_DIR_API)/$1/$(dir)/) +MODEST_UTILS_HDRS_CLONE_DIRS = $(foreach dir,$(strip $(patsubst %./,%,$(foreach path,$(call MODEST_UTILS_HDRS_CLONE_GDIR,$1,$2),$(dir $(path))))),mkdir -p $(dir) $(MODEST_UTILS_NEW_LINE)) +MODEST_UTILS_HDRS_CLONE = $(info Clone for $1) $(call MODEST_UTILS_HDRS_CLONE_DIRS,$1,$2) $(MODEST_UTILS_NEW_LINE) $(call MODEST_UTILS_HDRS_CLONE_CMND,$1,$2) -clean_include: - rm -rf $(INCLUDE_TMP) +#******************** +# Include all modules Makefile.mk +#*************** +include $(MODEST_BUILD_MODULES_MAKEFILES_LIST) -clone: create clean_include myhtml_clone mycss_clone modest_clone myfont_clone myurl_clone mycore_clone myencoding_clone - find include -name "*.h" -exec sed -i '.bak' -E 's/^[ \t]*#[ \t]*include[ \t]*"([^"]+)"/#include <\1>/g' {} \; - find include -name "*.h.bak" -exec rm -f {} \; +#******************** +# Set ARGS for flags +#*************** +CFLAGS += $(MODEST_CFLAGS) -test: - test/mycss/declaration test/mycss/data/declaration - test/myhtml/utils/avl_tree - test/myhtml/encoding_detect_meta test/myhtml/data/encoding/detect_meta.html - test/myurl/url test/myurl/data +#******************** +# Objects +#*************** +MODEST_BUILD_OBJECT_SHARED ?= $(CC) -shared $(IMP_FLAG) $(LDFLAGS) $1 -o $2 +MODEST_BUILD_OBJECT_MODULES := $(foreach dir,$(MODEST_BUILD_MODULES_TARGET),$($(dir)_objs)) -.PHONY: all clean clone test +#******************** +# Target options +#*************** +all: $(MODEST_BUILD_MODULES_TARGET_ALL) + $(call MODEST_BUILD_OBJECT_SHARED,$(MODEST_BUILD_OBJECT_MODULES),$(MODEST_LIBRARY)) + +clean: $(MODEST_BUILD_MODULES_TARGET_CLEAN) +clone: $(MODEST_BUILD_MODULES_TARGET_CLONE) + +.PHONY: all clean clone $(MODEST_BUILD_MODULES_TARGET_ALL) + +# SRCS := +# HDRS := +# EXTDIRS := examples test + +# all: create shared static +# for f in $(EXTDIRS); do $(MAKE) -C $$f all; done + +# include $(TARGET)/mycore/Makefile.mk +# include $(TARGET)/myencoding/Makefile.mk +# include $(TARGET)/myhtml/Makefile.mk +# include $(TARGET)/mycss/Makefile.mk +# include $(TARGET)/myfont/Makefile.mk +# include $(TARGET)/myurl/Makefile.mk +# include $(TARGET)/modest/Makefile.mk + +# OBJS := $(patsubst %.c,%.o,$(SRCS)) + +# shared: $(OBJS) +# $(CC) -shared $(IMP_FLAG) $(LDFLAGS) $(OBJS) -o $(LIB_TMP)/lib$(LIBNAME)$(LIBPOSTFIX) + +# static: shared +# $(AR) crus $(LIB_TMP)/lib$(LIBNAME)$(LIBSTATIC_POSTFIX).a $(OBJS) + +# create: +# mkdir -p lib bin + +# clean: +# for f in $(EXTDIRS); do $(MAKE) -C $$f clean; done +# rm -f $(OBJS) +# rm -f $(LIB_TMP)/* +# rm -f $(BIN_TMP)/* + +# clean_include: +# rm -rf $(INCLUDE_TMP) + +# clone: create clean_include myhtml_clone mycss_clone modest_clone myfont_clone myurl_clone mycore_clone myencoding_clone +# find include -name "*.h" -exec sed -i '.bak' -E 's/^[ \t]*#[ \t]*include[ \t]*"([^"]+)"/#include <\1>/g' {} \; +# find include -name "*.h.bak" -exec rm -f {} \; + +# test: +# test/mycss/declaration test/mycss/data/declaration +# test/myhtml/utils/avl_tree +# test/myhtml/encoding_detect_meta test/myhtml/data/encoding/detect_meta.html +# test/myurl/url test/myurl/data + +# .PHONY: all clean clone test diff --git a/Makefile.cfg b/Makefile.cfg new file mode 100644 index 0000000..fc750bb --- /dev/null +++ b/Makefile.cfg @@ -0,0 +1,69 @@ +MODEST_BUILD_OS := UNDEF + +# DEFAULT +MODEST_DIR_SEPARATOR ?= / + +# names +MODEST_LIBRARY ?= $(LIB_DIR_BASE)/lib$(LIB_NAME)$(LIB_NAME_SUFFIX) +MODEST_LIBRARY_STATIC ?= $(LIB_DIR_BASE)/lib$(LIB_NAME)$(LIB_NAME_SUFFIX_STATIC) +MODEST_PORT_NAME ?= posix + +# flags +MODEST_CFLAGS := -I$(INCLUDE_DIR) +OS ?= $(shell uname -s) + +#******************************* +# Windows_NT +#******************* +ifeq ($(OS),Windows_NT) + CFLAGS += -fPIC + + # Need set + MODEST_BUILD_OS := $(OS) + # this name eq source/myport/ + MODEST_PORT_NAME := windows +endif +# end of Windows_NT + +#******************************* +# Darwin, Mac OS X +#******************* +ifeq ($(OS),Darwin) + CFLAGS += -fPIC + + LIB_NAME_SUFFIX := .dylib + +# build without threads +ifeq ($(MODEST_BUILD_WITHOUT_THREADS),YES) + MODEST_CFLAGS += -DMODEST_BUILD_WITHOUT_THREADS +else + MODEST_LFLAGS += -pthread +endif + + # Need set + MODEST_BUILD_OS := $(OS) + # this name eq source/myport/ + MODEST_PORT_NAME := posix +endif +# end of Darwin, Mac OS X + +#******************************* +# POSIX +#******************* +ifeq ($(MODEST_BUILD_OS),UNDEF) + MODEST_CFLAGS += -fPIC + MODEST_CFLAGS += -D_POSIX_C_SOURCE=199309L + +# build without threads +ifeq ($(MODEST_BUILD_WITHOUT_THREADS),YES) + MODEST_CFLAGS += -DMODEST_BUILD_WITHOUT_THREADS +else + MODEST_LFLAGS += -pthread +endif + + # Need set + MODEST_BUILD_OS := $(OS) + # this name eq source/myport/ + MODEST_PORT_NAME := posix +endif +# end of POSIX diff --git a/include/modest/declaration.h b/include/modest/declaration.h index 7c19334..ab43889 100644 --- a/include/modest/declaration.h +++ b/include/modest/declaration.h @@ -22,10 +22,10 @@ #define MODEST_DECLARATION_H #pragma once -#include -#include -#include -#include +#include "modest/myosi.h" +#include "modest/node/node.h" +#include "modest/style/default.h" +#include "mycss/declaration/default.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/finder/finder.h b/include/modest/finder/finder.h index 8403094..ccc3f65 100644 --- a/include/modest/finder/finder.h +++ b/include/modest/finder/finder.h @@ -22,8 +22,8 @@ #define MODEST_FINDER_FINDER_H #pragma once -#include -#include +#include "modest/finder/myosi.h" +#include "modest/finder/type.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/finder/match.h b/include/modest/finder/match.h index 568f8af..adcf493 100644 --- a/include/modest/finder/match.h +++ b/include/modest/finder/match.h @@ -22,8 +22,8 @@ #define MODEST_FINDER_MATCH_H #pragma once -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/tree.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/finder/myosi.h b/include/modest/finder/myosi.h index 7dea0fe..eaf769d 100644 --- a/include/modest/finder/myosi.h +++ b/include/modest/finder/myosi.h @@ -22,10 +22,10 @@ #define MODEST_FINDER_MYOSI_H #pragma once -#include -#include -#include -#include +#include "modest/myosi.h" +#include "mycss/myosi.h" +#include "mycss/selectors/myosi.h" +#include "mycss/selectors/list.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/finder/pseudo_class.h b/include/modest/finder/pseudo_class.h index 05fd578..17c682a 100644 --- a/include/modest/finder/pseudo_class.h +++ b/include/modest/finder/pseudo_class.h @@ -22,8 +22,8 @@ #define MODEST_FINDER_PSEUDO_CLASS_H #pragma once -#include -#include +#include "modest/finder/myosi.h" +#include "modest/finder/finder.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/finder/thread.h b/include/modest/finder/thread.h index acb59a3..1e9b82e 100644 --- a/include/modest/finder/thread.h +++ b/include/modest/finder/thread.h @@ -22,17 +22,17 @@ #define MODEST_FINDER_THREAD_H #pragma once -#include -#include -#include -#include -#include -#include +#include "modest/modest.h" +#include "modest/node/node.h" +#include "modest/style/type.h" +#include "modest/style/map.h" +#include "modest/finder/myosi.h" +#include "modest/finder/finder.h" -#include -#include +#include "mycore/mythread.h" +#include "mycore/utils/mcobject_async.h" -#include +#include "mycss/declaration/myosi.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/finder/type.h b/include/modest/finder/type.h index bd56f14..39e573d 100644 --- a/include/modest/finder/type.h +++ b/include/modest/finder/type.h @@ -22,13 +22,13 @@ #define MODEST_FINDER_TYPE_H #pragma once -#include -#include -#include -#include -#include -#include -#include +#include "modest/finder/myosi.h" +#include "modest/finder/finder.h" +#include "modest/finder/pseudo_class.h" +#include "modest/finder/match.h" +#include "myhtml/tree.h" +#include "mycore/utils.h" +#include "mycss/selectors/value.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/glue.h b/include/modest/glue.h index d8b53f3..138fa46 100644 --- a/include/modest/glue.h +++ b/include/modest/glue.h @@ -22,8 +22,8 @@ #define MODEST_GLUE_H #pragma once -#include -#include +#include "modest/myosi.h" +#include "modest/node/node.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/layer/layer.h b/include/modest/layer/layer.h index 9a7c324..b72fe73 100644 --- a/include/modest/layer/layer.h +++ b/include/modest/layer/layer.h @@ -22,8 +22,8 @@ #define MODEST_LAYER_LAYER_H #pragma once -#include -#include +#include "modest/myosi.h" +#include "mycore/utils/mcobject.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/modest.h b/include/modest/modest.h index 373b8f7..daec9c5 100644 --- a/include/modest/modest.h +++ b/include/modest/modest.h @@ -22,12 +22,12 @@ #define MODEST_H #pragma once -#include -#include -#include -#include -#include -#include +#include "modest/myosi.h" +#include "modest/layer/layer.h" +#include "mycore/utils/mcobject.h" +#include "mycore/utils/mcobject_async.h" +#include "mycore/utils/mchar_async.h" +#include "mycore/utils/avl_tree.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/myosi.h b/include/modest/myosi.h index d6870b6..07a5135 100644 --- a/include/modest/myosi.h +++ b/include/modest/myosi.h @@ -22,8 +22,8 @@ #define MODEST_MYOSI_H #pragma once -#include -#include +#include "myhtml/myhtml.h" +#include "mycss/mycss.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/node/node.h b/include/modest/node/node.h index 6e212c7..0a459e9 100644 --- a/include/modest/node/node.h +++ b/include/modest/node/node.h @@ -22,11 +22,11 @@ #define MODEST_NODE_NODE_H #pragma once -#include -#include -#include -#include -#include +#include "modest/myosi.h" +#include "modest/modest.h" +#include "modest/style/raw.h" +#include "modest/render/tree_node.h" +#include "mycore/utils/avl_tree.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/node/property.h b/include/modest/node/property.h index 7f04f00..27190c0 100644 --- a/include/modest/node/property.h +++ b/include/modest/node/property.h @@ -22,7 +22,7 @@ #define MODEST_NODE_PROPERTY_H #pragma once -#include +#include "modest/node/node.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/node/raw_property.h b/include/modest/node/raw_property.h index 8a42f85..237cb63 100644 --- a/include/modest/node/raw_property.h +++ b/include/modest/node/raw_property.h @@ -22,7 +22,7 @@ #define MODEST_NODE_RAW_PROPERTY_H #pragma once -#include +#include "modest/node/node.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/node/serialization.h b/include/modest/node/serialization.h index 7d2d354..73f3828 100644 --- a/include/modest/node/serialization.h +++ b/include/modest/node/serialization.h @@ -22,11 +22,11 @@ #define MODEST_NODE_SERIALIZATION_H #pragma once -#include -#include -#include -#include -#include +#include "modest/myosi.h" +#include "modest/node/node.h" +#include "modest/node/raw_property.h" +#include "mycss/myosi.h" +#include "mycss/declaration/serialization.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/render/begin.h b/include/modest/render/begin.h index 6805d9b..53a2b99 100644 --- a/include/modest/render/begin.h +++ b/include/modest/render/begin.h @@ -22,9 +22,9 @@ #define MODEST_RENDER_BEGIN_H #pragma once -#include -#include -#include +#include "modest/modest.h" +#include "modest/style/type.h" +#include "modest/render/tree.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/render/binding.h b/include/modest/render/binding.h index 24a53ce..2f6ad5a 100644 --- a/include/modest/render/binding.h +++ b/include/modest/render/binding.h @@ -22,14 +22,14 @@ #define MODEST_RENDER_BINDING_H #pragma once -#include -#include -#include -#include -#include -#include +#include "modest/myosi.h" +#include "modest/modest.h" +#include "modest/node/node.h" +#include "modest/render/tree.h" +#include "modest/render/tree_node.h" +#include "modest/declaration.h" -#include +#include "myhtml/tree.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/render/tree.h b/include/modest/render/tree.h index a35333d..3b5d3c8 100644 --- a/include/modest/render/tree.h +++ b/include/modest/render/tree.h @@ -24,9 +24,9 @@ typedef struct modest_render_tree modest_render_tree_t; -#include -#include -#include +#include "modest/modest.h" +#include "mycore/utils/mcobject.h" +#include "modest/render/tree_node.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/render/tree_node.h b/include/modest/render/tree_node.h index 50fa2b7..6faccee 100644 --- a/include/modest/render/tree_node.h +++ b/include/modest/render/tree_node.h @@ -24,11 +24,11 @@ typedef struct modest_render_tree_node modest_render_tree_node_t; -#include -#include +#include "modest/modest.h" +#include "modest/render/tree.h" -#include -#include +#include "myhtml/tree.h" +#include "mycore/utils/mcobject.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/style/default.h b/include/modest/style/default.h index 3382ae5..d4eadc3 100644 --- a/include/modest/style/default.h +++ b/include/modest/style/default.h @@ -22,8 +22,8 @@ #define MODEST_STYLE_DEFAULT_H #pragma once -#include -#include +#include "modest/myosi.h" +#include "mycss/values/values.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/style/default_resources.h b/include/modest/style/default_resources.h index 5971d73..39d723d 100644 --- a/include/modest/style/default_resources.h +++ b/include/modest/style/default_resources.h @@ -22,7 +22,7 @@ #define MODEST_STYLE_DEFAULT_RESOURCES_H #pragma once -#include +#include "modest/style/default_entries.h" static const modest_style_default_by_html_node_f modest_style_default_function_of_declarations[MyHTML_TAG_LAST_ENTRY] = { diff --git a/include/modest/style/map.h b/include/modest/style/map.h index f142439..28174bf 100644 --- a/include/modest/style/map.h +++ b/include/modest/style/map.h @@ -22,10 +22,10 @@ #define MODEST_STYLE_MAP_H #pragma once -#include -#include -#include -#include +#include "modest/myosi.h" +#include "modest/modest.h" +#include "modest/finder/myosi.h" +#include "modest/finder/thread.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/style/raw.h b/include/modest/style/raw.h index b305448..ea93520 100644 --- a/include/modest/style/raw.h +++ b/include/modest/style/raw.h @@ -22,9 +22,9 @@ #define MODEST_STYLE_RAW_H #pragma once -#include -#include -#include +#include "modest/myosi.h" +#include "modest/modest.h" +#include "mycore/utils/mcobject.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/style/sheet.h b/include/modest/style/sheet.h index 2928365..030a803 100644 --- a/include/modest/style/sheet.h +++ b/include/modest/style/sheet.h @@ -22,9 +22,9 @@ #define MODEST_STYLE_SHEET_H #pragma once -#include -#include -#include +#include "modest/myosi.h" +#include "modest/modest.h" +#include "modest/style/type.h" #ifdef __cplusplus extern "C" { diff --git a/include/modest/style/type.h b/include/modest/style/type.h index 95ca2c6..762fc4a 100644 --- a/include/modest/style/type.h +++ b/include/modest/style/type.h @@ -22,10 +22,10 @@ #define MODEST_STYLE_TYPE_H #pragma once -#include -#include -#include -#include +#include "modest/myosi.h" +#include "modest/modest.h" +#include "mycss/declaration/myosi.h" +#include "mycore/utils/mchar_async.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycore/incoming.h b/include/mycore/incoming.h index 145666c..6b7afd9 100644 --- a/include/mycore/incoming.h +++ b/include/mycore/incoming.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "mycore/myosi.h" +#include "mycore/utils/mcobject.h" struct mycore_incoming_buffer { const char* data; diff --git a/include/mycore/myosi.h b/include/mycore/myosi.h index 72c2dc2..b96433f 100644 --- a/include/mycore/myosi.h +++ b/include/mycore/myosi.h @@ -27,12 +27,14 @@ #include #include #include -#include +#include #define MyCORE_VERSION_MAJOR 1 #define MyCORE_VERSION_MINOR 0 #define MyCORE_VERSION_PATCH 0 +#define MyCORE_BUILD_WITHOUT_THREADS + #ifdef __cplusplus //extern "C" { #endif @@ -60,14 +62,14 @@ /* Debug */ #ifdef MyCORE_DEBUG_MODE #define MyCORE_DEBUG(format, ...) \ - mycore_print(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) + mycore_fprintf(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) #else #define MyCORE_DEBUG(format, ...) #endif #ifdef MyCORE_DEBUG_MODE #define MyCORE_DEBUG_ERROR(format, ...) \ - mycore_print(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) + mycore_fprintf(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) #else #define MyCORE_DEBUG_ERROR(format, ...) #endif @@ -123,22 +125,16 @@ enum mycore_status { MyCORE_STATUS_MCOBJECT_ERROR_CACHE_CREATE = 0x0055, MyCORE_STATUS_MCOBJECT_ERROR_CHUNK_CREATE = 0x0056, MyCORE_STATUS_MCOBJECT_ERROR_CHUNK_INIT = 0x0057, - MyCORE_STATUS_MCOBJECT_ERROR_CACHE_REALLOC = 0x0058 + MyCORE_STATUS_MCOBJECT_ERROR_CACHE_REALLOC = 0x0058, + MyCORE_STATUS_ASYNC_ERROR_LOCK = 0x0060, + MyCORE_STATUS_ASYNC_ERROR_UNLOCK = 0x0061, + MyCORE_STATUS_ERROR_NO_FREE_SLOT = 0x0062, } typedef mycore_status_t; typedef unsigned int mystatus_t; /* thread */ -enum mythread_thread_opt { - MyTHREAD_OPT_UNDEF = 0x00, - MyTHREAD_OPT_WAIT = 0x01, - MyTHREAD_OPT_QUIT = 0x02, - MyTHREAD_OPT_STOP = 0x04, - MyTHREAD_OPT_DONE = 0x08 -} -typedef mythread_thread_opt_t; - typedef struct mythread_queue_list_entry mythread_queue_list_entry_t; typedef struct mythread_queue_thread_param mythread_queue_thread_param_t; typedef struct mythread_queue_list mythread_queue_list_t; @@ -146,9 +142,8 @@ typedef struct mythread_queue_node mythread_queue_node_t; typedef struct mythread_queue mythread_queue_t; typedef size_t mythread_id_t; -typedef struct mythread_workers_list mythread_workers_list_t; typedef struct mythread_context mythread_context_t; -typedef struct mythread_list mythread_list_t; +typedef struct mythread_entry mythread_entry_t; typedef struct mythread mythread_t; /* mystring */ @@ -164,9 +159,28 @@ typedef void (*mycore_callback_serialize_f)(const char* buffer, size_t size, voi void * mycore_malloc(size_t size); void * mycore_realloc(void* dst, size_t size); void * mycore_calloc(size_t num, size_t size); -void mycore_free(void* dst); +void * mycore_free(void* dst); + +/* io */ +int mycore_printf(const char* format, ...); +int mycore_fprintf(FILE* out, const char* format, ...); +int mycore_snprintf(char* buffer, size_t buffer_size, const char* format, ...); + +/** + * Platform-specific hdef performance clock queries. + * Implemented in perf.c + */ + +/** Get clock resolution */ +uint64_t mycore_hperf_res(mystatus_t *status); + +/** Get current value in clock ticks */ +uint64_t mycore_hperf_clock(mystatus_t *status); + +/** Print an hperf measure */ +mystatus_t mycore_hperf_print(const char *name, uint64_t x, uint64_t y, FILE *fh); +mystatus_t mycore_hperf_print_by_val(const char *name, uint64_t x, FILE *fh); -void mycore_print(FILE* out, const char* format, ...); #ifdef __cplusplus } /* extern "C" */ diff --git a/include/mycore/mystring.h b/include/mycore/mystring.h index d333583..30de718 100644 --- a/include/mycore/mystring.h +++ b/include/mycore/mystring.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycore/myosi.h" +#include "mycore/utils/mchar_async.h" +#include "mycore/utils.h" #define mycore_string_get(str, attr) str->attr #define mycore_string_set(str, attr) mycore_string_get(str, attr) diff --git a/include/mycore/mythread.h b/include/mycore/mythread.h new file mode 100644 index 0000000..c44ac47 --- /dev/null +++ b/include/mycore/mythread.h @@ -0,0 +1,159 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#ifndef MyCORE_THREAD_H +#define MyCORE_THREAD_H +#pragma once + +#ifdef __cplusplus +//extern "C" { +#endif + +#include "mycore/myosi.h" +#include "mycore/mystring.h" + +#ifdef MyCORE_BUILD_WITHOUT_THREADS + +struct mythread { + int sys_last_error; +}; + +#else +/* functions */ +typedef void (*mythread_callback_before_entry_join_f)(mythread_t* mythread, mythread_entry_t* entry, void* ctx); +typedef void (*mythread_process_f)(void* arg); +typedef void (*mythread_work_f)(mythread_id_t thread_id, void* arg); + +void mythread_function_queue_stream(void *arg); +void mythread_function_queue_batch(void *arg); +void mythread_function(void *arg); + +enum mythread_thread_opt { + MyTHREAD_OPT_UNDEF = 0x00, + MyTHREAD_OPT_WAIT = 0x01, + MyTHREAD_OPT_QUIT = 0x02, + MyTHREAD_OPT_STOP = 0x04, + MyTHREAD_OPT_DONE = 0x08 +} +typedef mythread_thread_opt_t; + +enum mythread_type { + MyTHREAD_TYPE_STREAM = 0x00, + MyTHREAD_TYPE_BATCH = 0x01 +} +typedef mythread_type_t; + +// thread +struct mythread_context { + mythread_id_t id; + mythread_work_f func; + + volatile size_t t_count; + volatile mythread_thread_opt_t opt; + + mystatus_t status; + + void* mutex; + void* timespec; + mythread_t* mythread; +}; + +struct mythread_entry { + void* thread; + + mythread_context_t context; + mythread_process_f process_func; +}; + +struct mythread { + mythread_entry_t *entries; + size_t entries_length; + size_t entries_size; + size_t id_increase; + + void* context; + void* attr; + void* timespec; + + int sys_last_error; + + mythread_type_t type; + volatile mythread_thread_opt_t opt; +}; + +mythread_t * mythread_create(void); +mystatus_t mythread_init(mythread_t *mythread, mythread_type_t type, size_t threads_count, size_t id_increase); +void mythread_clean(mythread_t *mythread); +mythread_t * mythread_destroy(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx, bool self_destroy); + +mythread_id_t myhread_increase_id_by_entry_id(mythread_t* mythread, mythread_id_t thread_id); + +/* set for all threads */ +mystatus_t mythread_join(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_quit(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_stop(mythread_t *mythread); +mystatus_t mythread_resume(mythread_t *mythread); +mystatus_t mythread_suspend(mythread_t *mythread); +mystatus_t mythread_check_status(mythread_t *mythread); + +mythread_thread_opt_t mythread_option(mythread_t *mythread); +void mythread_option_set(mythread_t *mythread, mythread_thread_opt_t opt); + +/* Entries */ +mystatus_t myhread_entry_create(mythread_t *mythread, mythread_process_f process_func, mythread_work_f func, mythread_thread_opt_t opt); + +mystatus_t mythread_entry_join(mythread_entry_t* entry, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_entry_quit(mythread_entry_t* entry, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_entry_stop(mythread_entry_t* entry); +mystatus_t mythread_entry_resume(mythread_entry_t* entry); +mystatus_t mythread_entry_suspend(mythread_entry_t* entry); +mystatus_t mythread_entry_status(mythread_entry_t* entry); +mythread_t * mythread_entry_mythread(mythread_entry_t* entry); + +/* API for ports */ +void * mythread_thread_create(mythread_t *mythread, void* process_func, void* ctx); +mystatus_t mythread_thread_join(mythread_t *mythread, void* thread); +mystatus_t mythread_thread_cancel(mythread_t *mythread, void* thread); +mystatus_t mythread_thread_destroy(mythread_t *mythread, void* thread); + +void * mythread_thread_attr_init(mythread_t *mythread); +void mythread_thread_attr_clean(mythread_t *mythread, void* attr); +void mythread_thread_attr_destroy(mythread_t *mythread, void* attr); + +void * mythread_mutex_create(mythread_t *mythread); +mystatus_t mythread_mutex_post(mythread_t *mythread, void* mutex); +mystatus_t mythread_mutex_wait(mythread_t *mythread, void* mutex); +void mythread_mutex_close(mythread_t *mythread, void* mutex); + +void * mythread_nanosleep_create(mythread_t* mythread); +void mythread_nanosleep_clean(void* timespec); +void mythread_nanosleep_destroy(void* timespec); +mystatus_t mythread_nanosleep_sleep(void* timespec); + +/* callback */ +void mythread_callback_quit(mythread_t* mythread, mythread_entry_t* entry, void* ctx); + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* MyCORE_THREAD_H */ diff --git a/include/mycore/thread.h b/include/mycore/thread.h deleted file mode 100644 index f43de44..0000000 --- a/include/mycore/thread.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - Copyright (C) 2015-2017 Alexander Borisov - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - Author: lex.borisov@gmail.com (Alexander Borisov) -*/ - -#ifndef MyCORE_THREAD_H -#define MyCORE_THREAD_H -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - -#if !defined(IS_OS_WINDOWS) -# include -# include -#endif - -#include -#include - -#include -#include - -#include - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -#define MyTHREAD_SEM_NAME "mycore" - -/* functions */ -typedef void (*mythread_callback_before_join_f)(mythread_t* mythread); -typedef void (*mythread_process_f)(void* arg); -typedef void (*mythread_work_f)(mythread_id_t thread_id, void* arg); - -#ifdef MyCORE_BUILD_WITHOUT_THREADS - -struct mythread { - int sys_last_error; -}; - -#else /* MyCORE_BUILD_WITHOUT_THREADS */ - -void mythread_function_queue_stream(void *arg); -void mythread_function_queue_batch(void *arg); -void mythread_function(void *arg); - -// thread -struct mythread_context { - mythread_id_t id; - -#if defined(IS_OS_WINDOWS) - HANDLE mutex; -#else - pthread_mutex_t *mutex; -#endif - - size_t sem_name_size; - - mythread_work_f func; - - volatile size_t t_count; - volatile mythread_thread_opt_t opt; - - mythread_t *mythread; - unsigned int status; -}; - -struct mythread_list { -#if defined(IS_OS_WINDOWS) - HANDLE pth; -#else - pthread_t pth; -#endif - mythread_context_t data; - mythread_process_f process_func; -}; - -struct mythread_workers_list { - mythread_list_t *list; - size_t count; -}; - -struct mythread { - mythread_list_t *pth_list; - size_t pth_list_length; - size_t pth_list_size; - size_t pth_list_root; - - void *context; - - char *sem_prefix; - size_t sem_prefix_length; - -#if !defined(IS_OS_WINDOWS) - pthread_attr_t *attr; -#endif - - int sys_last_error; - - mythread_id_t batch_first_id; - mythread_id_t batch_count; - - volatile mythread_thread_opt_t stream_opt; - volatile mythread_thread_opt_t batch_opt; -}; - -mythread_id_t myhread_create_stream(mythread_t *mythread, mythread_process_f process_func, mythread_work_f func, mythread_thread_opt_t opt, mystatus_t *status); -mythread_id_t myhread_create_batch(mythread_t *mythread, mythread_process_f process_func, mythread_work_f func, mythread_thread_opt_t opt, mystatus_t *status, size_t count); - -void mycore_thread_nanosleep(const struct timespec *tomeout); - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -mythread_t * mythread_create(void); -mystatus_t mythread_init(mythread_t *mythread, const char *sem_prefix, size_t thread_count); -void mythread_clean(mythread_t *mythread); -mythread_t * mythread_destroy(mythread_t *mythread, mythread_callback_before_join_f before_join, bool self_destroy); - -void mythread_stream_quit_all(mythread_t *mythread); -void mythread_batch_quit_all(mythread_t *mythread); - -void mythread_stream_stop_all(mythread_t *mythread); -void mythread_batch_stop_all(mythread_t *mythread); - -void mythread_stop_all(mythread_t *mythread); -void mythread_queue_wait_all_for_done(mythread_t *mythread); -void mythread_resume_all(mythread_t *mythread); -void mythread_suspend_all(mythread_t *mythread); -unsigned int mythread_check_status(mythread_t *mythread); - -// queue -struct mythread_queue_node { - void* context; - void* args; - - mythread_queue_node_t* prev; -}; - -struct mythread_queue_thread_param { - volatile size_t use; -}; - -struct mythread_queue_list_entry { - mythread_queue_list_entry_t *next; - mythread_queue_list_entry_t *prev; - mythread_queue_t *queue; - mythread_queue_thread_param_t *thread_param; -}; - -struct mythread_queue_list { - mythread_queue_list_entry_t *first; - mythread_queue_list_entry_t *last; - - volatile size_t count; -}; - -struct mythread_queue { - mythread_queue_node_t **nodes; - - size_t nodes_pos; - size_t nodes_pos_size; - size_t nodes_length; - - volatile size_t nodes_uses; - volatile size_t nodes_size; - volatile size_t nodes_root; -}; - -mythread_queue_t * mythread_queue_create(size_t size, mystatus_t *status); -void mythread_queue_clean(mythread_queue_t* queue); -mythread_queue_t * mythread_queue_destroy(mythread_queue_t* token); - -void mythread_queue_node_clean(mythread_queue_node_t* qnode); - -size_t mythread_queue_count_used_node(mythread_queue_t* queue); -mythread_queue_node_t * mythread_queue_get_first_node(mythread_queue_t* queue); -mythread_queue_node_t * mythread_queue_get_prev_node(mythread_queue_node_t* qnode); -mythread_queue_node_t * mythread_queue_get_current_node(mythread_queue_t* queue); -mythread_queue_node_t * mythread_queue_node_malloc(mythread_t *mythread, mythread_queue_t* queue, mystatus_t *status); -mythread_queue_node_t * mythread_queue_node_malloc_limit(mythread_t *mythread, mythread_queue_t* queue, size_t limit, mystatus_t *status); - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - -mythread_queue_list_t * mythread_queue_list_create(mystatus_t *status); -void mythread_queue_list_destroy(mythread_queue_list_t* queue_list); - -size_t mythread_queue_list_get_count(mythread_queue_list_t* queue_list); - -mythread_queue_list_entry_t * mythread_queue_list_entry_push(mythread_t *mythread, mythread_queue_t *queue, mystatus_t *status); -mythread_queue_list_entry_t * mythread_queue_list_entry_delete(mythread_t *mythread, mythread_queue_list_entry_t *entry, bool destroy_queue); -void mythread_queue_list_entry_clean(mythread_t *mythread, mythread_queue_list_entry_t *entry); -void mythread_queue_list_entry_wait_for_done(mythread_t *mythread, mythread_queue_list_entry_t *entry); - -mythread_queue_node_t * mythread_queue_node_malloc_round(mythread_t *mythread, mythread_queue_list_entry_t *entry, mystatus_t *status); - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* defined(__mycore__mycore_thread__) */ - diff --git a/include/mycore/thread_queue.h b/include/mycore/thread_queue.h new file mode 100644 index 0000000..7311714 --- /dev/null +++ b/include/mycore/thread_queue.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#ifndef MyCORE_THREAD_QUEUE_H +#define MyCORE_THREAD_QUEUE_H +#pragma once + +#include "mycore/myosi.h" +#include "mycore/mythread.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +// queue +struct mythread_queue_node { + void* context; + void* args; + + mythread_queue_node_t* prev; +}; + +struct mythread_queue_thread_param { + volatile size_t use; +}; + +struct mythread_queue_list_entry { + mythread_queue_t* queue; + mythread_queue_thread_param_t* thread_param; + size_t thread_param_size; + + mythread_queue_list_entry_t* next; + mythread_queue_list_entry_t* prev; +}; + +struct mythread_queue_list { + mythread_queue_list_entry_t *first; + mythread_queue_list_entry_t *last; + + volatile size_t count; +}; + +struct mythread_queue { + mythread_queue_node_t **nodes; + + size_t nodes_pos; + size_t nodes_pos_size; + size_t nodes_length; + + volatile size_t nodes_uses; + volatile size_t nodes_size; + volatile size_t nodes_root; +}; + +mythread_queue_t * mythread_queue_create(void); +mystatus_t mythread_queue_init(mythread_queue_t* queue, size_t size); +void mythread_queue_clean(mythread_queue_t* queue); +mythread_queue_t * mythread_queue_destroy(mythread_queue_t* token); + +void mythread_queue_node_clean(mythread_queue_node_t* qnode); +size_t mythread_queue_count_used_node(mythread_queue_t* queue); + +mythread_queue_node_t * mythread_queue_get_first_node(mythread_queue_t* queue); +mythread_queue_node_t * mythread_queue_get_prev_node(mythread_queue_node_t* qnode); +mythread_queue_node_t * mythread_queue_get_current_node(mythread_queue_t* queue); + +mythread_queue_node_t * mythread_queue_node_malloc(mythread_t *mythread, mythread_queue_t* queue, mystatus_t *status); +mythread_queue_node_t * mythread_queue_node_malloc_limit(mythread_t *mythread, mythread_queue_t* queue, size_t limit, mystatus_t *status); +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mythread_queue_node_t * mythread_queue_node_malloc_round(mythread_t *mythread, mythread_queue_list_entry_t *entry, mystatus_t *status); +#endif + +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mythread_queue_list_t * mythread_queue_list_create(mystatus_t *status); +void mythread_queue_list_destroy(mythread_queue_list_t* queue_list); +size_t mythread_queue_list_get_count(mythread_queue_list_t* queue_list); + +void mythread_queue_list_wait_for_done(mythread_t* mythread, mythread_queue_list_t* queue_list); +bool mythread_queue_list_see_for_done(mythread_t* mythread, mythread_queue_list_t* queue_list); +bool mythread_queue_list_see_for_done_by_thread(mythread_t* mythread, mythread_queue_list_t* queue_list, mythread_id_t thread_id); + +mythread_queue_list_entry_t * mythread_queue_list_entry_push(mythread_t** mythread_list, size_t list_size, mythread_queue_list_t* queue_list, mythread_queue_t* queue, size_t thread_param_size, mystatus_t* status); +mythread_queue_list_entry_t * mythread_queue_list_entry_delete(mythread_t** mythread_list, size_t list_size, mythread_queue_list_t *queue_list, mythread_queue_list_entry_t *entry, bool destroy_queue); +void mythread_queue_list_entry_clean(mythread_queue_list_entry_t *entry); +void mythread_queue_list_entry_wait_for_done(mythread_t *mythread, mythread_queue_list_entry_t *entry); +void mythread_queue_list_entry_make_batch(mythread_t* mythread, mythread_queue_list_entry_t* entry, size_t from, size_t length); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* MyCORE_THREAD_QUEUE_H */ diff --git a/include/mycore/utils.h b/include/mycore/utils.h index e4a7e9f..f926cb7 100644 --- a/include/mycore/utils.h +++ b/include/mycore/utils.h @@ -26,7 +26,7 @@ extern "C" { #endif -#include +#include "mycore/myosi.h" #define mycore_utils_whithspace(onechar, action, logic) \ (onechar action ' ' logic \ diff --git a/include/mycore/utils/avl_tree.h b/include/mycore/utils/avl_tree.h index 5242468..2ab7ecb 100644 --- a/include/mycore/utils/avl_tree.h +++ b/include/mycore/utils/avl_tree.h @@ -22,8 +22,8 @@ #define MyCORE_UTILS_AVL_TREE_H #pragma once -#include -#include +#include "mycore/myosi.h" +#include "mycore/utils/mcobject.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycore/utils/mchar_async.h b/include/mycore/utils/mchar_async.h index 8806587..f7fe54b 100644 --- a/include/mycore/utils/mchar_async.h +++ b/include/mycore/utils/mchar_async.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "mycore/myosi.h" +#include "mycore/utils/mcsync.h" #define mchar_async_cache_has_nodes(cache) cache.count @@ -96,16 +96,16 @@ struct mchar_async { typedef mchar_async_t; -mchar_async_t * mchar_async_create(size_t pos_size, size_t size); -void mchar_async_init(mchar_async_t *mchar_async, size_t chunk_len, size_t char_size); -void mchar_async_clean(mchar_async_t *mchar_async); +mchar_async_t * mchar_async_create(void); +mystatus_t mchar_async_init(mchar_async_t *mchar_async, size_t chunk_len, size_t char_size); +mystatus_t mchar_async_clean(mchar_async_t *mchar_async); mchar_async_t * mchar_async_destroy(mchar_async_t *mchar_async, int destroy_self); char * mchar_async_malloc(mchar_async_t *mchar_async, size_t node_idx, size_t size); char * mchar_async_realloc(mchar_async_t *mchar_async, size_t node_idx, char *data, size_t data_len, size_t new_size); void mchar_async_free(mchar_async_t *mchar_async, size_t node_idx, char *entry); -size_t mchar_async_node_add(mchar_async_t *mchar_async); +size_t mchar_async_node_add(mchar_async_t *mchar_async, mystatus_t* status); void mchar_async_node_clean(mchar_async_t *mchar_async, size_t node_idx); void mchar_async_node_delete(mchar_async_t *mchar_async, size_t node_idx); @@ -116,7 +116,7 @@ char * mchar_async_crop_first_chars_without_cache(char *data, size_t crop_len); size_t mchar_async_get_size_by_data(const char *data); // cache -void mchar_async_cache_init(mchar_async_cache_t *cache); +mystatus_t mchar_async_cache_init(mchar_async_cache_t *cache); mchar_async_cache_t * mchar_async_cache_destroy(mchar_async_cache_t *cache, bool self_destroy); void mchar_async_cache_clean(mchar_async_cache_t *cache); diff --git a/include/mycore/utils/mcobject.h b/include/mycore/utils/mcobject.h index 1ba6893..a38e937 100644 --- a/include/mycore/utils/mcobject.h +++ b/include/mycore/utils/mcobject.h @@ -26,7 +26,7 @@ extern "C" { #endif -#include +#include "mycore/myosi.h" struct mcobject_chunk { unsigned char *begin; diff --git a/include/mycore/utils/mcobject_async.h b/include/mycore/utils/mcobject_async.h index 2b09b3c..41252ff 100644 --- a/include/mycore/utils/mcobject_async.h +++ b/include/mycore/utils/mcobject_async.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "mycore/myosi.h" +#include "mycore/utils/mcsync.h" enum mcobject_async_status { MCOBJECT_ASYNC_STATUS_OK = 0, diff --git a/include/mycore/utils/mcsimple.h b/include/mycore/utils/mcsimple.h index 90fd87d..9eae399 100644 --- a/include/mycore/utils/mcsimple.h +++ b/include/mycore/utils/mcsimple.h @@ -26,7 +26,7 @@ extern "C" { #endif -#include +#include "mycore/myosi.h" struct mcsimple { size_t struct_size; diff --git a/include/mycore/utils/mcsync.h b/include/mycore/utils/mcsync.h index fad2934..80fa896 100644 --- a/include/mycore/utils/mcsync.h +++ b/include/mycore/utils/mcsync.h @@ -22,37 +22,22 @@ #define MyCORE_UTILS_MCSYNC_H #pragma once +#include "mycore/myosi.h" + #ifdef __cplusplus extern "C" { #endif - -#include -#include -#include - -#include - -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) -#if defined(IS_OS_WINDOWS) - typedef CRITICAL_SECTION pthread_mutex_t; - typedef unsigned long pthread_mutexattr_t; -#else -# include -#endif -#endif enum mcsync_status { - MCSYNC_STATUS_OK = 0, - MCSYNC_STATUS_NOT_OK = 1, - MCSYNC_STATUS_ERROR_MEM_ALLOCATE = 2 + MCSYNC_STATUS_OK = 0x00, + MCSYNC_STATUS_NOT_OK = 0x01, + MCSYNC_STATUS_ERROR_MEM_ALLOCATE = 0x02 } typedef mcsync_status_t; struct mcsync { - int spinlock; -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) - pthread_mutex_t *mutex; -#endif + int* spinlock; + void* mutex; } typedef mcsync_t; @@ -61,37 +46,26 @@ mcsync_status_t mcsync_init(mcsync_t* mcsync); void mcsync_clean(mcsync_t* mcsync); mcsync_t * mcsync_destroy(mcsync_t* mcsync, int destroy_self); -mcsync_status_t mcsync_lock(mcsync_t* mclock); -mcsync_status_t mcsync_unlock(mcsync_t* mclock); +mcsync_status_t mcsync_lock(mcsync_t* mcsync); +mcsync_status_t mcsync_unlock(mcsync_t* mcsync); -mcsync_status_t mcsync_mutex_lock(mcsync_t* mclock); -mcsync_status_t mcsync_mutex_unlock(mcsync_t* mclock); +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mcsync_status_t mcsync_spin_lock(void* spinlock); +mcsync_status_t mcsync_spin_unlock(void* spinlock); -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) && defined(IS_OS_WINDOWS) -static __inline int pthread_mutex_lock(pthread_mutex_t *mutex) -{ - EnterCriticalSection(mutex); - return 0; -} +mcsync_status_t mcsync_mutex_lock(void* mutex); +mcsync_status_t mcsync_mutex_try_lock(void* mutex); +mcsync_status_t mcsync_mutex_unlock(void* mutex); -static __inline int pthread_mutex_unlock(pthread_mutex_t *mutex) -{ - LeaveCriticalSection(mutex); - return 0; -} +void * mcsync_spin_create(void); +mcsync_status_t mcsync_spin_init(void* spinlock); +void mcsync_spin_clean(void* spinlock); +void mcsync_spin_destroy(void* spinlock); -static __inline int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *a) -{ - (void)a; - InitializeCriticalSection(mutex); - return 0; -} - -static __inline int pthread_mutex_destroy(pthread_mutex_t *mutex) -{ - DeleteCriticalSection(mutex); - return 0; -} +void * mcsync_mutex_create(void); +mcsync_status_t mcsync_mutex_init(void* mutex); +void mcsync_mutex_clean(void* mutex); +void mcsync_mutex_destroy(void* mutex); #endif #ifdef __cplusplus diff --git a/include/mycore/utils/mctree.h b/include/mycore/utils/mctree.h index 98bb6ba..2d848c3 100644 --- a/include/mycore/utils/mctree.h +++ b/include/mycore/utils/mctree.h @@ -22,8 +22,8 @@ #define MyCORE_UTILS_MCTREE_H #pragma once -#include -#include +#include "mycore/myosi.h" +#include "mycore/utils.h" #include #include diff --git a/include/mycore/utils/mhash.h b/include/mycore/utils/mhash.h index 6f7902d..2d7fd99 100644 --- a/include/mycore/utils/mhash.h +++ b/include/mycore/utils/mhash.h @@ -21,8 +21,8 @@ #ifndef MyCORE_UTILS_MHASH_H #define MyCORE_UTILS_MHASH_H -#include -#include +#include "mycore/myosi.h" +#include "mycore/utils/mchar_async.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/an_plus_b.h b/include/mycss/an_plus_b.h index 3b39d9a..3a8f53e 100644 --- a/include/mycss/an_plus_b.h +++ b/include/mycss/an_plus_b.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/list.h" #define mycss_an_plus_b_current_entry(entry) (*entry->anb->entry) diff --git a/include/mycss/check.h b/include/mycss/check.h index 2f8f39c..1d0ab5c 100644 --- a/include/mycss/check.h +++ b/include/mycss/check.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/mycss.h" +#include "mycss/entry.h" bool mycss_check_three_code_points_would_start_identifier(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size); bool mycss_check_two_code_points_valid_escape(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size); diff --git a/include/mycss/convert.h b/include/mycss/convert.h index d74cbfb..8d841a2 100644 --- a/include/mycss/convert.h +++ b/include/mycss/convert.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/entry.h" +#include "myhtml/mystring.h" const char * mycss_convert_split_dimension_string(mycore_string_t* str, double* value, bool* is_float); diff --git a/include/mycss/declaration/default.h b/include/mycss/declaration/default.h index 565e7e9..49cc968 100644 --- a/include/mycss/declaration/default.h +++ b/include/mycss/declaration/default.h @@ -22,8 +22,8 @@ #define MyCSS_DECLARATION_DEFAULT_H #pragma once -#include -#include +#include "mycss/declaration/myosi.h" +#include "mycss/values/values.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/declaration/default_resources.h b/include/mycss/declaration/default_resources.h index 9c96d47..682e305 100644 --- a/include/mycss/declaration/default_resources.h +++ b/include/mycss/declaration/default_resources.h @@ -22,7 +22,7 @@ #define MyCSS_DECLARATION_DEFAULT_RESOURCES_H #pragma once -#include +#include "mycss/declaration/default_entries.h" static mycss_declaration_entry_t * mycss_declaration_default_entry_index_type[MyCSS_PROPERTY_TYPE_LAST_ENTRY] = { diff --git a/include/mycss/declaration/entry.h b/include/mycss/declaration/entry.h index 44cb145..2d49b92 100644 --- a/include/mycss/declaration/entry.h +++ b/include/mycss/declaration/entry.h @@ -22,10 +22,10 @@ #define MyHTML_MyCSS_DECLARATION_ENTRY_H #pragma once -#include -#include -#include -#include +#include "mycss/declaration/myosi.h" +#include "mycss/declaration/entry_destroy.h" +#include "mycss/values/values.h" +#include "mycss/property/init.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/declaration/entry_destroy.h b/include/mycss/declaration/entry_destroy.h index 3e6e774..f946a75 100644 --- a/include/mycss/declaration/entry_destroy.h +++ b/include/mycss/declaration/entry_destroy.h @@ -22,9 +22,9 @@ #define MyCSS_DECLARATION_ENTRY_DESTROY_H #pragma once -#include -#include -#include +#include "mycss/declaration/myosi.h" +#include "mycss/values/values.h" +#include "mycss/values/destroy.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/declaration/init.h b/include/mycss/declaration/init.h index 6fab0ab..ec73ec7 100644 --- a/include/mycss/declaration/init.h +++ b/include/mycss/declaration/init.h @@ -22,8 +22,8 @@ #define MyHTML_MyCSS_DECLARATION_INIT_H #pragma once -#include -#include +#include "mycss/declaration/myosi.h" +#include "mycss/entry.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/declaration/myosi.h b/include/mycss/declaration/myosi.h index 57a3b8e..5a454ef 100644 --- a/include/mycss/declaration/myosi.h +++ b/include/mycss/declaration/myosi.h @@ -22,11 +22,11 @@ #define MyHTML_MyCSS_DECLARATION_MYOSI_H #pragma once -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/stack.h" +#include "mycss/values/units.h" +#include "mycss/property/myosi.h" +#include "mycore/utils/mcobject.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/declaration/parser.h b/include/mycss/declaration/parser.h index ab4e4c2..ee94963 100644 --- a/include/mycss/declaration/parser.h +++ b/include/mycss/declaration/parser.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/property/init.h" +#include "mycss/declaration/entry.h" void mycss_declaration_parser_begin(mycss_entry_t* entry, mycss_token_t* token); void mycss_declaration_parser_ident(mycss_entry_t* entry, mycss_token_t* token); diff --git a/include/mycss/declaration/serialization.h b/include/mycss/declaration/serialization.h index 04f92e8..b6fe723 100644 --- a/include/mycss/declaration/serialization.h +++ b/include/mycss/declaration/serialization.h @@ -22,10 +22,10 @@ #define MyHTML_MyCSS_DECLARATION_SERIALIZATION_H #pragma once -#include -#include -#include -#include +#include "mycss/declaration/myosi.h" +#include "mycss/values/values.h" +#include "mycss/property/init.h" +#include "mycss/property/serialization.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/declaration/state.h b/include/mycss/declaration/state.h index 4616196..0884a21 100644 --- a/include/mycss/declaration/state.h +++ b/include/mycss/declaration/state.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "mycss/entry.h" +#include "mycss/declaration/parser.h" bool mycss_declaration_state_begin(mycss_entry_t* entry, mycss_token_t* token, bool last_response); diff --git a/include/mycss/entry.h b/include/mycss/entry.h index 930668f..79a5523 100644 --- a/include/mycss/entry.h +++ b/include/mycss/entry.h @@ -26,22 +26,22 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/mycss.h" +#include "mycss/parser.h" +#include "mycss/stylesheet.h" +#include "mycss/namespace/myosi.h" +#include "mycss/namespace/init.h" +#include "mycss/selectors/myosi.h" +#include "mycss/selectors/init.h" +#include "mycss/an_plus_b.h" +#include "mycss/declaration/myosi.h" +#include "mycss/declaration/init.h" +#include "mycss/declaration/entry.h" +#include "mycss/media/myosi.h" +#include "mycss/media/init.h" +#include "mycore/utils/mcobject.h" +#include "mycore/utils/mchar_async.h" struct mycss_entry_parser_list_entry { mycss_parser_token_f parser; diff --git a/include/mycss/media/init.h b/include/mycss/media/init.h index 97ff354..038ee2d 100644 --- a/include/mycss/media/init.h +++ b/include/mycss/media/init.h @@ -22,7 +22,7 @@ #define MyHTML_MyCSS_MEDIA_INIT_H #pragma once -#include +#include "mycss/media/myosi.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/media/myosi.h b/include/mycss/media/myosi.h index ef45cc3..10a55af 100644 --- a/include/mycss/media/myosi.h +++ b/include/mycss/media/myosi.h @@ -22,7 +22,7 @@ #define MyHTML_MyCSS_MEDIA_MYOSI_H #pragma once -#include +#include "mycss/myosi.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/media/state.h b/include/mycss/media/state.h index 29a4f87..aeda0e4 100644 --- a/include/mycss/media/state.h +++ b/include/mycss/media/state.h @@ -22,8 +22,8 @@ #define MyHTML_MyCSS_MEDIA_STATE_H #pragma once -#include -#include +#include "mycss/media/myosi.h" +#include "mycss/entry.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/mycss.h b/include/mycss/mycss.h index d20fd2c..4d66e51 100644 --- a/include/mycss/mycss.h +++ b/include/mycss/mycss.h @@ -28,23 +28,23 @@ extern "C" { #ifdef MyCSS_DEBUG #define MyCSS_DEBUG_MESSAGE(format, ...) \ - mycore_print(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) + mycore_fprintf(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) #else #define MyCSS_DEBUG_MESSAGE(format, ...) #endif #ifdef DEBUG_MODE #define MyCORE_DEBUG_ERROR(format, ...) \ -mycore_print(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) +mycore_fprintf(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) #else #define MyCORE_DEBUG_ERROR(format, ...) #endif -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/entry.h" +#include "mycss/tokenizer.h" +#include "myhtml/myhtml.h" +#include "mycore/utils/mcobject_async.h" struct mycss { mycss_tokenizer_state_f* parse_state_func; diff --git a/include/mycss/myosi.h b/include/mycss/myosi.h index 0504557..56ad768 100644 --- a/include/mycss/myosi.h +++ b/include/mycss/myosi.h @@ -26,7 +26,7 @@ extern "C" { #endif -#include +#include "myhtml/myosi.h" // base /* diff --git a/include/mycss/mystring.h b/include/mycss/mystring.h index 1b61645..2aaf812 100644 --- a/include/mycss/mystring.h +++ b/include/mycss/mystring.h @@ -26,10 +26,10 @@ extern "C" { #endif -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycore/incoming.h" +#include "mycore/mystring.h" +#include "myencoding/encoding.h" enum mycss_string_process_state { MyCSS_STRING_PROCESS_STATE_DATA = 0x00, diff --git a/include/mycss/namespace/init.h b/include/mycss/namespace/init.h index a79f91a..05bd46e 100644 --- a/include/mycss/namespace/init.h +++ b/include/mycss/namespace/init.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/namespace/myosi.h" +#include "mycss/entry.h" +#include "myhtml/mynamespace.h" mycss_namespace_t * mycss_namespace_create(void); mystatus_t mycss_namespace_init(mycss_entry_t* entry, mycss_namespace_t* ns); diff --git a/include/mycss/namespace/myosi.h b/include/mycss/namespace/myosi.h index 2fa2632..a033229 100644 --- a/include/mycss/namespace/myosi.h +++ b/include/mycss/namespace/myosi.h @@ -26,10 +26,10 @@ extern "C" { #endif -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "myhtml/mystring.h" +#include "mycore/utils/mctree.h" +#include "mycore/utils/mcobject.h" typedef struct mycss_namespace mycss_namespace_t; typedef struct mycss_namespace_entry mycss_namespace_entry_t; diff --git a/include/mycss/namespace/parser.h b/include/mycss/namespace/parser.h index 8e45697..d319c7b 100644 --- a/include/mycss/namespace/parser.h +++ b/include/mycss/namespace/parser.h @@ -26,10 +26,10 @@ extern "C" { #endif -#include -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/namespace/myosi.h" +#include "myhtml/mynamespace.h" +#include "mycore/utils/mctree.h" void mycss_namespace_parser_begin(mycss_entry_t* entry); diff --git a/include/mycss/namespace/serialization.h b/include/mycss/namespace/serialization.h index 0dd5c15..1e87f3e 100644 --- a/include/mycss/namespace/serialization.h +++ b/include/mycss/namespace/serialization.h @@ -22,8 +22,8 @@ #define MyHTML_MyCSS_NAMESPACE_SERIALIZATION_H #pragma once -#include -#include +#include "mycss/entry.h" +#include "mycss/namespace/myosi.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/namespace/state.h b/include/mycss/namespace/state.h index fdf81e4..4134a5f 100644 --- a/include/mycss/namespace/state.h +++ b/include/mycss/namespace/state.h @@ -26,10 +26,10 @@ extern "C" { #endif -#include -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/namespace/myosi.h" +#include "mycss/namespace/parser.h" +#include "mycore/utils.h" bool mycss_namespace_state_namespace(mycss_entry_t* entry, mycss_token_t* token, bool last_response); bool mycss_namespace_state_namespace_namespace(mycss_entry_t* entry, mycss_token_t* token, bool last_response); diff --git a/include/mycss/parser.h b/include/mycss/parser.h index 82d29c5..f5e06ef 100644 --- a/include/mycss/parser.h +++ b/include/mycss/parser.h @@ -26,16 +26,16 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/mycss.h" +#include "mycss/entry.h" +#include "mycss/mystring.h" +#include "mycss/convert.h" +#include "mycss/namespace/state.h" +#include "mycss/selectors/state.h" +#include "mycss/selectors/parser.h" +#include "mycss/declaration/state.h" +#include "mycore/incoming.h" mycss_token_t * mycss_parser_token_ready_callback_function(mycss_entry_t* entry, mycss_token_t* token); diff --git a/include/mycss/property/init.h b/include/mycss/property/init.h index e2a934f..00fac17 100644 --- a/include/mycss/property/init.h +++ b/include/mycss/property/init.h @@ -22,10 +22,10 @@ #define MyHTML_MyCSS_PROPERTY_INIT_H #pragma once -#include -#include -#include -#include +#include "mycss/property/myosi.h" +#include "mycss/property/parser.h" +#include "mycss/values/serialization.h" +#include "mycore/utils.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/property/myosi.h b/include/mycss/property/myosi.h index 1dce753..f1e50e3 100644 --- a/include/mycss/property/myosi.h +++ b/include/mycss/property/myosi.h @@ -22,8 +22,8 @@ #define MyHTML_MyCSS_PROPERTY_MYOSI_H #pragma once -#include -#include +#include "mycss/myosi.h" +#include "mycss/property/const.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/property/parser.h b/include/mycss/property/parser.h index df181b6..2a2fa22 100644 --- a/include/mycss/property/parser.h +++ b/include/mycss/property/parser.h @@ -22,11 +22,11 @@ #define MyHTML_MyCSS_PROPERTY_PARSER_H #pragma once -#include -#include -#include -#include -#include +#include "mycss/property/myosi.h" +#include "mycss/property/shared.h" +#include "mycss/values/consume.h" +#include "mycss/values/values.h" +#include "mycss/declaration/entry.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/property/serialization.h b/include/mycss/property/serialization.h index 748d52d..2f1abb7 100644 --- a/include/mycss/property/serialization.h +++ b/include/mycss/property/serialization.h @@ -22,9 +22,9 @@ #define MyHTML_MyCSS_PROPERTY_SERIALIZATION_H #pragma once -#include -#include -#include +#include "mycss/property/myosi.h" +#include "mycss/property/init.h" +#include "mycss/values/serialization.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/property/shared.h b/include/mycss/property/shared.h index 5357bd6..c7e38ae 100644 --- a/include/mycss/property/shared.h +++ b/include/mycss/property/shared.h @@ -22,12 +22,12 @@ #define MyHTML_MyCSS_PROPERTY_SHARED_H #pragma once -#include -#include -#include -#include -#include -#include +#include "mycss/property/myosi.h" +#include "mycss/values/consume.h" +#include "mycss/values/values.h" +#include "mycss/values/color.h" +#include "mycss/values/image.h" +#include "mycore/utils.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/selectors/function.h b/include/mycss/selectors/function.h index 7f73f05..beea322 100644 --- a/include/mycss/selectors/function.h +++ b/include/mycss/selectors/function.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/myosi.h" +#include "mycss/selectors/function_parser.h" typedef void (*mycss_selectors_function_begin_f)(mycss_entry_t* entry, mycss_selectors_entry_t* selector); diff --git a/include/mycss/selectors/function_parser.h b/include/mycss/selectors/function_parser.h index f619dd3..a0e67c2 100644 --- a/include/mycss/selectors/function_parser.h +++ b/include/mycss/selectors/function_parser.h @@ -28,8 +28,8 @@ extern "C" { #endif -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/myosi.h" bool mycss_selectors_function_parser_state_drop_component_value(mycss_entry_t* entry, mycss_token_t* token, bool last_response); diff --git a/include/mycss/selectors/init.h b/include/mycss/selectors/init.h index 6ac470f..c06773f 100644 --- a/include/mycss/selectors/init.h +++ b/include/mycss/selectors/init.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/myosi.h" +#include "mycss/selectors/list.h" mycss_selectors_t * mycss_selectors_create(void); mystatus_t mycss_selectors_init(mycss_entry_t* entry, mycss_selectors_t* selectors); diff --git a/include/mycss/selectors/list.h b/include/mycss/selectors/list.h index 1320494..73bcc2c 100644 --- a/include/mycss/selectors/list.h +++ b/include/mycss/selectors/list.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/myosi.h" +#include "mycss/declaration/myosi.h" struct mycss_selectors_entries_list { mycss_selectors_entry_t* entry; diff --git a/include/mycss/selectors/myosi.h b/include/mycss/selectors/myosi.h index c81e5ac..b0e32b4 100644 --- a/include/mycss/selectors/myosi.h +++ b/include/mycss/selectors/myosi.h @@ -32,11 +32,11 @@ typedef struct mycss_selectors_entries_list mycss_selectors_entries_list_t; typedef struct mycss_selectors_list mycss_selectors_list_t; typedef struct mycss_selectors_specificity mycss_selectors_specificity_t; -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/mystring.h" +#include "mycss/namespace/myosi.h" +#include "mycss/declaration/myosi.h" +#include "mycore/utils/mcobject.h" typedef bool (*mycss_selectors_state_f)(mycss_entry_t* entry, mycss_selectors_t* selectors, mycss_selectors_entry_t* selector, mycss_token_t* token); typedef void (*mycss_callback_selector_done_f)(mycss_selectors_t* selectors, mycss_selectors_entry_t* selector); diff --git a/include/mycss/selectors/parser.h b/include/mycss/selectors/parser.h index f8be137..78b7898 100644 --- a/include/mycss/selectors/parser.h +++ b/include/mycss/selectors/parser.h @@ -26,13 +26,13 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/namespace/myosi.h" +#include "mycss/namespace/init.h" +#include "mycss/selectors/myosi.h" +#include "mycss/selectors/value.h" +#include "mycss/selectors/function.h" +#include "mycss/selectors/pseudo.h" void mycss_selectors_parser_selector_begin(mycss_entry_t* entry, mycss_token_t* token); void mycss_selectors_parser_selector_ident_type(mycss_entry_t* entry, mycss_token_t* token); diff --git a/include/mycss/selectors/pseudo.h b/include/mycss/selectors/pseudo.h index 470ba8d..84f3e83 100644 --- a/include/mycss/selectors/pseudo.h +++ b/include/mycss/selectors/pseudo.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/myosi.h" struct mycss_selectots_pseudo_begin_entry { const char* name; diff --git a/include/mycss/selectors/serialization.h b/include/mycss/selectors/serialization.h index e2038d5..7d9d0cc 100644 --- a/include/mycss/selectors/serialization.h +++ b/include/mycss/selectors/serialization.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/selectors/myosi.h" +#include "mycss/namespace/serialization.h" +#include "mycss/declaration/serialization.h" void mycss_selectors_serialization_chain(mycss_selectors_t* selectors, mycss_selectors_entry_t* selector, mycss_callback_serialization_f callback, void* context); bool mycss_selectors_serialization_list(mycss_selectors_t* selectors, mycss_selectors_list_t* selectors_list, mycss_callback_serialization_f callback, void* context); diff --git a/include/mycss/selectors/state.h b/include/mycss/selectors/state.h index a5f87e0..b88a2b8 100644 --- a/include/mycss/selectors/state.h +++ b/include/mycss/selectors/state.h @@ -26,10 +26,10 @@ extern "C" { #endif -#include -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/myosi.h" +#include "mycss/selectors/parser.h" +#include "mycore/utils.h" void mycss_selectors_state_end(mycss_entry_t* entry); bool mycss_selectors_state_function_skip_all(mycss_entry_t* entry, mycss_token_t* token, bool last_response); diff --git a/include/mycss/selectors/value.h b/include/mycss/selectors/value.h index d21dba7..d22e04d 100644 --- a/include/mycss/selectors/value.h +++ b/include/mycss/selectors/value.h @@ -34,9 +34,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/entry.h" +#include "mycss/selectors/myosi.h" +#include "mycore/utils/mchar_async.h" typedef void * (*mycss_selectors_value_destroy_f)(mycss_entry_t* entry, mycss_selectors_type_t type, int sub_type, void* value, bool self_destroy); typedef void * (*mycss_selectors_value_function_destroy_f)(mycss_entry_t* entry, void* value, bool self_destroy); diff --git a/include/mycss/selectors/value_resource.h b/include/mycss/selectors/value_resource.h index f40fdb0..328fd62 100644 --- a/include/mycss/selectors/value_resource.h +++ b/include/mycss/selectors/value_resource.h @@ -22,7 +22,7 @@ #define MyHTML_MyCSS_SELECTORS_VALUE_RESOURCE_H #pragma once -#include +#include "mycss/selectors/myosi.h" static const mycss_selectors_value_destroy_f mycss_selectors_value_destroy_map[MyCSS_SELECTORS_TYPE_LAST_ENTRY] = { mycss_selectors_value_undef_destroy, /* MyCSS_SELECTORS_TYPE_UNDEF */ diff --git a/include/mycss/stack.h b/include/mycss/stack.h index 5a8d4f9..4904cea 100644 --- a/include/mycss/stack.h +++ b/include/mycss/stack.h @@ -22,7 +22,7 @@ #define MyCSS_STACK_H #pragma once -#include +#include "mycss/myosi.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/stylesheet.h b/include/mycss/stylesheet.h index 175f21c..7ecd74b 100644 --- a/include/mycss/stylesheet.h +++ b/include/mycss/stylesheet.h @@ -22,11 +22,11 @@ #define MyHTML_MyCSS_STYLESHEET_H #pragma once -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/entry.h" +#include "mycss/namespace/myosi.h" +#include "mycss/selectors/myosi.h" +#include "mycss/selectors/serialization.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/tokenizer.h b/include/mycss/tokenizer.h index c73a3c4..c3c789c 100644 --- a/include/mycss/tokenizer.h +++ b/include/mycss/tokenizer.h @@ -26,14 +26,14 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/mycss.h" +#include "mycss/entry.h" +#include "mycss/check.h" +#include "mycss/tokenizer_global.h" +#include "mycss/tokenizer_end.h" -#include +#include "mycore/incoming.h" #define MyCSS_TOKEN_READY_CALLBACK_FUNCTION(ENTRY, TOKEN) \ ++ENTRY->token_counter; \ diff --git a/include/mycss/tokenizer_end.h b/include/mycss/tokenizer_end.h index f7c4e61..590f1e0 100644 --- a/include/mycss/tokenizer_end.h +++ b/include/mycss/tokenizer_end.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/mycss.h" +#include "mycss/entry.h" size_t mycss_tokenizer_end_run_state_single(mycss_entry_t* entry, mycss_tokenizer_state_t state, const char* css, size_t css_offset, size_t css_size); diff --git a/include/mycss/tokenizer_global.h b/include/mycss/tokenizer_global.h index 4a9d5da..37327d6 100644 --- a/include/mycss/tokenizer_global.h +++ b/include/mycss/tokenizer_global.h @@ -26,10 +26,10 @@ extern "C" { #endif -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/mycss.h" +#include "mycss/entry.h" +#include "mycss/check.h" size_t mycss_tokenizer_global_back(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size); diff --git a/include/mycss/values/color.h b/include/mycss/values/color.h index fa92a7e..1220c77 100644 --- a/include/mycss/values/color.h +++ b/include/mycss/values/color.h @@ -22,10 +22,10 @@ #define MyCSS_VALUES_COLOR_H #pragma once -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/values/values.h" +#include "mycss/values/color_const.h" +#include "mycss/values/color_parser.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/values/color_parser.h b/include/mycss/values/color_parser.h index e009b95..ad997c5 100644 --- a/include/mycss/values/color_parser.h +++ b/include/mycss/values/color_parser.h @@ -22,9 +22,9 @@ #define MyCSS_VALUES_COLOR_PARSER_H #pragma once -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/values/consume.h" +#include "mycss/values/values.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/values/consume.h b/include/mycss/values/consume.h index 2113db7..1a8441e 100644 --- a/include/mycss/values/consume.h +++ b/include/mycss/values/consume.h @@ -22,10 +22,10 @@ #define MyHTML_MyCSS_VALUES_CONSUME_H #pragma once -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/entry.h" +#include "mycss/values/values.h" +#include "mycss/values/units.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/values/destroy.h b/include/mycss/values/destroy.h index 29670a0..7f5e2b1 100644 --- a/include/mycss/values/destroy.h +++ b/include/mycss/values/destroy.h @@ -22,8 +22,8 @@ #define MyCSS_VALUES_DESTROY_H #pragma once -#include -#include +#include "mycss/values/values.h" +#include "mycss/declaration/entry.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/values/image.h b/include/mycss/values/image.h index ed6b9dc..888f926 100644 --- a/include/mycss/values/image.h +++ b/include/mycss/values/image.h @@ -22,9 +22,9 @@ #define MyCSS_VALUES_IMAGE_H #pragma once -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/values/values.h" +#include "mycss/property/parser.h" #ifdef __cplusplus extern "C" { diff --git a/include/mycss/values/serialization.h b/include/mycss/values/serialization.h index c55c873..240a8e2 100644 --- a/include/mycss/values/serialization.h +++ b/include/mycss/values/serialization.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "mycss/values/values.h" +#include "mycss/values/color.h" +#include "mycss/property/const.h" void mycss_values_serialization_string(mycore_string_t* str, mycss_callback_serialization_f callback, void* context); void mycss_values_serialization_number(mycss_values_number_t* value, mycss_callback_serialization_f callback, void* context); diff --git a/include/mycss/values/units.h b/include/mycss/values/units.h index 6e6f09f..ff1566d 100644 --- a/include/mycss/values/units.h +++ b/include/mycss/values/units.h @@ -22,8 +22,8 @@ #define MyHTML_MyCSS_VALUES_UNITS_H #pragma once -#include -#include +#include "mycss/myosi.h" +#include "mycore/utils.h" #define mycss_units_is_angel_type(type) (type >= 1 && type <= 4) #define mycss_units_is_frequency_type(type) (type >= 5 && type <= 6) diff --git a/include/mycss/values/values.h b/include/mycss/values/values.h index b559692..92c98a3 100644 --- a/include/mycss/values/values.h +++ b/include/mycss/values/values.h @@ -22,13 +22,13 @@ #define MyHTML_MyCSS_VALUES_VALUES_H #pragma once -#include -#include -#include -#include -#include -#include -#include +#include "mycss/myosi.h" +#include "mycss/values/units.h" +#include "mycss/values/color_const.h" +#include "mycss/property/const.h" +#include "mycore/utils/mchar_async.h" +#include "myhtml/mystring.h" +#include "mycss/declaration/myosi.h" #ifdef __cplusplus extern "C" { diff --git a/include/myencoding/detect_resource.h b/include/myencoding/detect_resource.h index 3aba646..2e33713 100644 --- a/include/myencoding/detect_resource.h +++ b/include/myencoding/detect_resource.h @@ -28,7 +28,7 @@ extern "C" { #define MyENCODING_DETECT_NAME_STATIC_SIZE 419 -#include +#include "myencoding/encoding.h" static const myencoding_detect_name_entry_t myencoding_detect_name_entry_static_list_index[] = { diff --git a/include/myencoding/encoding.h b/include/myencoding/encoding.h index 8247308..19cfcea 100644 --- a/include/myencoding/encoding.h +++ b/include/myencoding/encoding.h @@ -26,9 +26,9 @@ //extern "C" { #endif -#include -#include -#include +#include "myencoding/myosi.h" +#include "mycore/utils.h" +#include "mycore/mystring.h" struct myencoding_result { unsigned long first; diff --git a/include/myencoding/myosi.h b/include/myencoding/myosi.h index e9ab80d..ad09f8e 100644 --- a/include/myencoding/myosi.h +++ b/include/myencoding/myosi.h @@ -22,7 +22,7 @@ #define MyENCODING_MYOSI_H #pragma once -#include +#include "mycore/myosi.h" #define MyENCODING_VERSION_MAJOR 1 #define MyENCODING_VERSION_MINOR 0 diff --git a/include/myencoding/mystring.h b/include/myencoding/mystring.h index bc347a7..38f7f75 100644 --- a/include/myencoding/mystring.h +++ b/include/myencoding/mystring.h @@ -26,10 +26,10 @@ //extern "C" { #endif -#include -#include -#include -#include +#include "myencoding/myosi.h" +#include "myencoding/encoding.h" +#include "mycore/mystring.h" +#include "mycore/utils.h" void myencoding_string_append(mycore_string_t* str, const char* buff, size_t length, myencoding_t encoding); diff --git a/include/myencoding/resource.h b/include/myencoding/resource.h index 9c8e845..12f4a73 100644 --- a/include/myencoding/resource.h +++ b/include/myencoding/resource.h @@ -18,7 +18,7 @@ Author: lex.borisov@gmail.com (Alexander Borisov) */ -#include +#include "myencoding/encoding.h" #ifndef MyENCODING_RESOURCE_H #define MyENCODING_RESOURCE_H diff --git a/include/myfont/cmap.h b/include/myfont/cmap.h index 42227f8..b6a08c9 100644 --- a/include/myfont/cmap.h +++ b/include/myfont/cmap.h @@ -22,7 +22,7 @@ #define MyFONT_CMAP_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -206,7 +206,7 @@ struct myfont_table_cmap { } typedef myfont_table_cmap_t; -#include +#include "myfont/myfont.h" mystatus_t myfont_load_table_cmap(myfont_font_t *mf); diff --git a/include/myfont/glyf.h b/include/myfont/glyf.h index c7a67c0..991ce6a 100644 --- a/include/myfont/glyf.h +++ b/include/myfont/glyf.h @@ -22,7 +22,7 @@ #define MyFONT_GLYF_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -95,7 +95,7 @@ struct myfont_table_glyf { } typedef myfont_table_glyf_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/head.h b/include/myfont/head.h index 7e5544f..dcde2ae 100644 --- a/include/myfont/head.h +++ b/include/myfont/head.h @@ -22,7 +22,7 @@ #define MyFONT_HEAD_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -49,7 +49,7 @@ struct myfont_table_head { } typedef myfont_table_head_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/hhea.h b/include/myfont/hhea.h index b7b7e73..c08a330 100644 --- a/include/myfont/hhea.h +++ b/include/myfont/hhea.h @@ -22,7 +22,7 @@ #define MyFONT_HHEA_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -50,7 +50,7 @@ struct myfont_table_hhea { } typedef myfont_table_hhea_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/hmtx.h b/include/myfont/hmtx.h index d2da06b..225d6c2 100644 --- a/include/myfont/hmtx.h +++ b/include/myfont/hmtx.h @@ -22,7 +22,7 @@ #define MyFONT_HMTX_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -41,7 +41,7 @@ struct myfont_table_hmtx { } typedef myfont_table_hmtx_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/loca.h b/include/myfont/loca.h index 9b86318..63abc70 100644 --- a/include/myfont/loca.h +++ b/include/myfont/loca.h @@ -22,7 +22,7 @@ #define MyFONT_LOCA_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -34,7 +34,7 @@ struct myfont_table_loca { } typedef myfont_table_loca_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/maxp.h b/include/myfont/maxp.h index 6a7ef8f..66b3c22 100644 --- a/include/myfont/maxp.h +++ b/include/myfont/maxp.h @@ -22,7 +22,7 @@ #define MyFONT_MAXP_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -47,7 +47,7 @@ struct myfont_table_maxp { } typedef myfont_table_maxp_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/myfont.h b/include/myfont/myfont.h index 87d72a1..67a02c1 100644 --- a/include/myfont/myfont.h +++ b/include/myfont/myfont.h @@ -22,21 +22,21 @@ #define MyFONT_MyFONT_H #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "myfont/myosi.h" +#include "myfont/cmap.h" +#include "myfont/head.h" +#include "myfont/name.h" +#include "myfont/os_2.h" +#include "myfont/maxp.h" +#include "myfont/hhea.h" +#include "myfont/hmtx.h" +#include "myfont/glyf.h" +#include "myfont/vhea.h" +#include "myfont/vmtx.h" +#include "myfont/pclt.h" +#include "myfont/loca.h" -#include +#include "mycore/utils/mchar_async.h" #ifdef __cplusplus extern "C" { diff --git a/include/myfont/myosi.h b/include/myfont/myosi.h index 4e4aab4..dc15c68 100644 --- a/include/myfont/myosi.h +++ b/include/myfont/myosi.h @@ -24,7 +24,7 @@ #define MyFONT_BASE_H #pragma once -#include +#include "myhtml/myosi.h" // Required Tables #define MyFONT_TABLE_TYPE_cmap 1885433187 diff --git a/include/myfont/name.h b/include/myfont/name.h index c6f1572..0b47ef0 100644 --- a/include/myfont/name.h +++ b/include/myfont/name.h @@ -22,7 +22,7 @@ #define MyFONT_NAME_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -56,7 +56,7 @@ struct myfont_table_name { } typedef myfont_table_name_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/os_2.h b/include/myfont/os_2.h index 9e0f207..773a32f 100644 --- a/include/myfont/os_2.h +++ b/include/myfont/os_2.h @@ -22,7 +22,7 @@ #define MyFONT_OS_2_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -86,7 +86,7 @@ struct myfont_table_os_2 { } typedef myfont_table_os_2_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/pclt.h b/include/myfont/pclt.h index ea0adde..d61591d 100644 --- a/include/myfont/pclt.h +++ b/include/myfont/pclt.h @@ -22,7 +22,7 @@ #define MyFONT_PCLT_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -48,7 +48,7 @@ struct myfont_table_pclt { } typedef myfont_table_pclt_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/vhea.h b/include/myfont/vhea.h index ebda523..2b20eca 100644 --- a/include/myfont/vhea.h +++ b/include/myfont/vhea.h @@ -22,7 +22,7 @@ #define MyFONT_VHEA_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -50,7 +50,7 @@ struct myfont_table_vhea { } typedef myfont_table_vhea_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myfont/vmtx.h b/include/myfont/vmtx.h index cdd7456..35021ab 100644 --- a/include/myfont/vmtx.h +++ b/include/myfont/vmtx.h @@ -22,7 +22,7 @@ #define MyFONT_VMTX_H #pragma once -#include +#include "myfont/myosi.h" #ifdef __cplusplus extern "C" { @@ -41,7 +41,7 @@ struct myfont_table_vmtx { } typedef myfont_table_vmtx_t; -#include +#include "myfont/myfont.h" struct myfont_font; diff --git a/include/myhtml/api.h b/include/myhtml/api.h index 0c54fcd..c07b6f3 100755 --- a/include/myhtml/api.h +++ b/include/myhtml/api.h @@ -1724,10 +1724,11 @@ myhtml_token_node_is_close_self(myhtml_token_node_t *token_node); /** * Wait for process token all parsing stage. Need if you use thread mode * + * @param[in] myhtml_token_t* * @param[in] myhtml_token_node_t* */ void -myhtml_token_node_wait_for_done(myhtml_token_node_t* node); +myhtml_token_node_wait_for_done(myhtml_token_t* token, myhtml_token_node_t* node); /*********************************************************************************** * diff --git a/include/myhtml/callback.h b/include/myhtml/callback.h index c29dbe6..fd6420a 100644 --- a/include/myhtml/callback.h +++ b/include/myhtml/callback.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/tree.h" /* callback functions */ myhtml_callback_token_f myhtml_callback_before_token_done(myhtml_tree_t *tree); diff --git a/include/myhtml/charef.h b/include/myhtml/charef.h index d98dfc6..53e3436 100644 --- a/include/myhtml/charef.h +++ b/include/myhtml/charef.h @@ -26,7 +26,7 @@ extern "C" { #endif -#include +#include "myhtml/myosi.h" struct charef_entry { unsigned char ch; diff --git a/include/myhtml/data_process.h b/include/myhtml/data_process.h index 029e568..eb977e3 100644 --- a/include/myhtml/data_process.h +++ b/include/myhtml/data_process.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/charef.h" +#include "myhtml/mystring.h" struct myhtml_data_process_entry { /* current state for process data */ diff --git a/include/myhtml/myhtml.h b/include/myhtml/myhtml.h index 463e153..2b0d353 100644 --- a/include/myhtml/myhtml.h +++ b/include/myhtml/myhtml.h @@ -26,22 +26,22 @@ extern "C" { #endif -#include +#include "myhtml/myosi.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "mycore/utils/mctree.h" +#include "mycore/utils/mcobject_async.h" +#include "mycore/mythread.h" +#include "mycore/incoming.h" +#include "myencoding/encoding.h" +#include "myhtml/tree.h" +#include "myhtml/tag.h" +#include "myhtml/def.h" +#include "myhtml/parser.h" +#include "myhtml/tokenizer.h" +#include "myhtml/rules.h" +#include "myhtml/token.h" +#include "myhtml/charef.h" +#include "myhtml/callback.h" #define mh_queue_current() tree->queue #define myhtml_tokenizer_state_set(tree) myhtml_tree_set(tree, state) @@ -65,8 +65,10 @@ extern "C" { (onechar < 'A' || onechar > 'Z')) struct myhtml { - mythread_t *thread; - //mchar_async_t *mchar; // for all + mythread_t* thread_stream; + mythread_t* thread_batch; + mythread_t* thread_list[3]; + size_t thread_total; myhtml_tokenizer_state_f* parse_state_func; myhtml_insertion_f* insertion_func; @@ -215,21 +217,6 @@ bool myhtml_is_html_node(myhtml_tree_node_t *node, myhtml_tag_id_t tag_id); // queue mystatus_t myhtml_queue_add(myhtml_tree_t *tree, size_t begin, myhtml_token_node_t* token); -/** - * Platform-specific hdef performance clock queries. - * Implemented in perf.c - */ - -/** Get clock resolution */ -uint64_t myhtml_hperf_res(mystatus_t *status); - -/** Get current value in clock ticks */ -uint64_t myhtml_hperf_clock(mystatus_t *status); - -/** Print an hperf measure */ -mystatus_t myhtml_hperf_print(const char *name, uint64_t x, uint64_t y, FILE *fh); -mystatus_t myhtml_hperf_print_by_val(const char *name, uint64_t x, FILE *fh); - /* version */ myhtml_version_t myhtml_version(void); diff --git a/include/myhtml/mynamespace.h b/include/myhtml/mynamespace.h index 49dbe67..1f08fe7 100644 --- a/include/myhtml/mynamespace.h +++ b/include/myhtml/mynamespace.h @@ -30,8 +30,8 @@ extern "C" { #include -#include -#include +#include "myhtml/myosi.h" +#include "mycore/utils.h" struct myhtml_namespace_detect_name_entry { const char* name; diff --git a/include/myhtml/myosi.h b/include/myhtml/myosi.h index b954e25..aced165 100644 --- a/include/myhtml/myosi.h +++ b/include/myhtml/myosi.h @@ -22,7 +22,7 @@ #define MyHTML_MYOSI_H #pragma once -#include +#include "mycore/myosi.h" #define MyHTML_VERSION_MAJOR 3 #define MyHTML_VERSION_MINOR 0 diff --git a/include/myhtml/mystring.h b/include/myhtml/mystring.h index 3275f95..bdef549 100644 --- a/include/myhtml/mystring.h +++ b/include/myhtml/mystring.h @@ -26,13 +26,13 @@ //extern "C" { #endif -#include +#include "myhtml/myosi.h" -#include -#include +#include "myencoding/encoding.h" +#include "myencoding/mystring.h" -#include -#include +#include "mycore/mystring.h" +#include "mycore/utils/mchar_async.h" #define myhtml_string_get(str, attr) str->attr #define myhtml_string_set(str, attr) myhtml_string_get(str, attr) diff --git a/include/myhtml/parser.h b/include/myhtml/parser.h index c2129a4..ef3be41 100644 --- a/include/myhtml/parser.h +++ b/include/myhtml/parser.h @@ -26,12 +26,12 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/myhtml.h" +#include "myhtml/mystring.h" +#include "myhtml/tree.h" +#include "myhtml/token.h" +#include "myhtml/data_process.h" void myhtml_parser_stream(mythread_id_t thread_id, void* ctx); void myhtml_parser_worker(mythread_id_t thread_id, void* ctx); diff --git a/include/myhtml/rules.h b/include/myhtml/rules.h index 84c7102..8d52143 100644 --- a/include/myhtml/rules.h +++ b/include/myhtml/rules.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/myhtml.h" +#include "myhtml/tree.h" mystatus_t myhtml_rules_init(myhtml_t* myhtml); void myhtml_rules_stop_parsing(myhtml_tree_t* tree); diff --git a/include/myhtml/serialization.h b/include/myhtml/serialization.h index 8bc22b7..62a6065 100644 --- a/include/myhtml/serialization.h +++ b/include/myhtml/serialization.h @@ -22,9 +22,9 @@ #define MyHTML_SERIALIZATION_H #pragma once -#include -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/mystring.h" +#include "myhtml/tree.h" #ifdef __cplusplus extern "C" { diff --git a/include/myhtml/stream.h b/include/myhtml/stream.h index 1ff6f55..814735e 100644 --- a/include/myhtml/stream.h +++ b/include/myhtml/stream.h @@ -26,8 +26,8 @@ extern "C" { #endif -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/myhtml.h" struct myhtml_stream_buffer_entry { diff --git a/include/myhtml/tag.h b/include/myhtml/tag.h index 174f336..cb85ce8 100644 --- a/include/myhtml/tag.h +++ b/include/myhtml/tag.h @@ -26,17 +26,17 @@ extern "C" { #endif -#include +#include "myhtml/myosi.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "myhtml/tag_const.h" +#include "myhtml/tokenizer.h" +#include "myhtml/tree.h" +#include "mycore/utils.h" +#include "mycore/utils/mctree.h" +#include "mycore/utils/mchar_async.h" +#include "mycore/utils/mcobject.h" +#include "mycore/utils/mcobject_async.h" +#include "mycore/utils/mcsimple.h" #define myhtml_tag_get(tags, idx, attr) tags->context[idx].attr diff --git a/include/myhtml/token.h b/include/myhtml/token.h index daec35b..5d7b629 100644 --- a/include/myhtml/token.h +++ b/include/myhtml/token.h @@ -28,14 +28,14 @@ extern "C" { #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "myhtml/myosi.h" +#include "mycore/utils.h" +#include "myhtml/tag.h" +#include "myhtml/myhtml.h" +#include "myhtml/mystring.h" +#include "mycore/utils/mcobject_async.h" +#include "mycore/utils/mchar_async.h" +#include "mycore/utils/mcsync.h" #define myhtml_token_node_set_done(token_node) token_node->type |= MyHTML_TOKEN_TYPE_DONE @@ -130,7 +130,7 @@ myhtml_token_attr_t * myhtml_token_attr_remove_by_name(myhtml_token_node_t* node void myhtml_token_attr_delete_all(myhtml_token_t* token, myhtml_token_node_t* node); void myhtml_token_delete(myhtml_token_t* token, myhtml_token_node_t* node); -void myhtml_token_node_wait_for_done(myhtml_token_node_t* node); +void myhtml_token_node_wait_for_done(myhtml_token_t* token, myhtml_token_node_t* node); void myhtml_token_set_done(myhtml_token_node_t* node); myhtml_token_attr_t * myhtml_token_attr_match(myhtml_token_t* token, myhtml_token_node_t* target, const char* key, size_t key_size, const char* value, size_t value_size); diff --git a/include/myhtml/tokenizer.h b/include/myhtml/tokenizer.h index 4204db4..c5b7219 100644 --- a/include/myhtml/tokenizer.h +++ b/include/myhtml/tokenizer.h @@ -26,14 +26,14 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include -#include -#include +#include "myhtml/myosi.h" +#include "mycore/utils.h" +#include "mycore/mythread.h" +#include "myhtml/myhtml.h" +#include "myhtml/tag.h" +#include "myhtml/tokenizer_doctype.h" +#include "myhtml/tokenizer_script.h" +#include "myhtml/tokenizer_end.h" #define myhtml_tokenizer_inc_html_offset(offset, size) \ offset++; \ diff --git a/include/myhtml/tokenizer_doctype.h b/include/myhtml/tokenizer_doctype.h index 1f13a87..216b007 100644 --- a/include/myhtml/tokenizer_doctype.h +++ b/include/myhtml/tokenizer_doctype.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "myhtml/myosi.h" +#include "mycore/utils.h" +#include "myhtml/myhtml.h" size_t myhtml_tokenizer_state_doctype(myhtml_tree_t* tree, myhtml_token_node_t* token_node, const char* html, size_t html_offset, size_t html_size); size_t myhtml_tokenizer_state_before_doctype_name(myhtml_tree_t* tree, myhtml_token_node_t* token_node, const char* html, size_t html_offset, size_t html_size); diff --git a/include/myhtml/tokenizer_end.h b/include/myhtml/tokenizer_end.h index 4087ecc..3d78807 100644 --- a/include/myhtml/tokenizer_end.h +++ b/include/myhtml/tokenizer_end.h @@ -26,9 +26,9 @@ extern "C" { #endif -#include -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/myhtml.h" +#include "myhtml/tokenizer.h" size_t myhtml_tokenizer_end_state_data(myhtml_tree_t* tree, myhtml_token_node_t* token_node, const char* html, size_t html_offset, size_t html_size); size_t myhtml_tokenizer_end_state_tag_open(myhtml_tree_t* tree, myhtml_token_node_t* token_node, const char* html, size_t html_offset, size_t html_size); diff --git a/include/myhtml/tokenizer_script.h b/include/myhtml/tokenizer_script.h index 420380e..2a76783 100644 --- a/include/myhtml/tokenizer_script.h +++ b/include/myhtml/tokenizer_script.h @@ -26,10 +26,10 @@ extern "C" { #endif -#include -#include -#include -#include +#include "myhtml/myosi.h" +#include "mycore/utils.h" +#include "myhtml/myhtml.h" +#include "myhtml/tokenizer.h" size_t myhtml_tokenizer_state_script_data(myhtml_tree_t* tree, myhtml_token_node_t* token_node, const char* html, size_t html_offset, size_t html_size); size_t myhtml_tokenizer_state_script_data_less_than_sign(myhtml_tree_t* tree, myhtml_token_node_t* token_node, const char* html, size_t html_offset, size_t html_size); diff --git a/include/myhtml/tree.h b/include/myhtml/tree.h index 31b4267..e98ad44 100644 --- a/include/myhtml/tree.h +++ b/include/myhtml/tree.h @@ -26,15 +26,16 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "myhtml/myosi.h" +#include "myhtml/myhtml.h" +#include "myhtml/mystring.h" +#include "myhtml/token.h" +#include "myhtml/stream.h" +#include "mycore/thread_queue.h" +#include "mycore/utils/mcsync.h" +#include "mycore/utils/mchar_async.h" +#include "mycore/utils/mcobject.h" +#include "mycore/utils/mcobject_async.h" #define myhtml_tree_get(tree, attr) tree->attr #define myhtml_tree_set(tree, attr) tree->attr @@ -185,6 +186,11 @@ struct myhtml_tree { size_t mcasync_rules_token_id; size_t mcasync_rules_attr_id; size_t mcasync_tree_id; + /* + * mchar_node_id + * for rules, or if single mode, + * or for main thread only after parsing + */ size_t mchar_node_id; myhtml_token_attr_t* attr_current; myhtml_tag_id_t tmp_tag_id; @@ -227,7 +233,7 @@ struct myhtml_tree { volatile myhtml_tree_parse_flags_t parse_flags; bool foster_parenting; size_t global_offset; - mystatus_t tokenizer_status; + mystatus_t tokenizer_status; myencoding_t encoding; myencoding_t encoding_usereq; diff --git a/include/myunicode/myosi.h b/include/myunicode/myosi.h new file mode 100644 index 0000000..fd25d26 --- /dev/null +++ b/include/myunicode/myosi.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#ifndef MyUNICODE_MYOSI_H +#define MyUNICODE_MYOSI_H +#pragma once + +#include "myhtml/myosi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* MyUNICODE_MYOSI_H */ diff --git a/include/myurl/host.h b/include/myurl/host.h index d8bd65f..4a8b31f 100644 --- a/include/myurl/host.h +++ b/include/myurl/host.h @@ -22,11 +22,11 @@ #define MyURL_HOST_H #pragma once -#include -#include +#include "myurl/myosi.h" +#include "myhtml/mystring.h" -#include -#include +#include "myurl/parser.h" +#include "myurl/utils.h" #ifdef __cplusplus extern "C" { diff --git a/include/myurl/myosi.h b/include/myurl/myosi.h index 6eedb72..60fff08 100644 --- a/include/myurl/myosi.h +++ b/include/myurl/myosi.h @@ -22,7 +22,7 @@ #define MyURL_MYOSI_H #pragma once -#include +#include "myhtml/myosi.h" #ifdef __cplusplus extern "C" { diff --git a/include/myurl/parser.h b/include/myurl/parser.h index 47a2ad3..dc4e82f 100644 --- a/include/myurl/parser.h +++ b/include/myurl/parser.h @@ -22,8 +22,8 @@ #define MyURL_PARSER_H #pragma once -#include -#include +#include "myurl/myosi.h" +#include "myurl/utils.h" #define myurl_parser_digit(onechar) (onechar >= 0x30 && onechar <= 0x39) #define myurl_parser_alpha_upper(onechar) (onechar >= 0x41 && onechar <= 0x5A) diff --git a/include/myurl/path.h b/include/myurl/path.h index e18abf3..4d8f0c3 100644 --- a/include/myurl/path.h +++ b/include/myurl/path.h @@ -18,10 +18,10 @@ Author: lex.borisov@gmail.com (Alexander Borisov) */ -#include -#include -#include -#include +#include "myurl/myosi.h" +#include "myurl/scheme_const.h" +#include "myurl/utils.h" +#include "myhtml/mystring.h" #ifndef MyURL_PATH_H #define MyURL_PATH_H diff --git a/include/myurl/punycode.h b/include/myurl/punycode.h index e9d7aab..297fd5b 100644 --- a/include/myurl/punycode.h +++ b/include/myurl/punycode.h @@ -22,9 +22,9 @@ #define MyURL_PUNYCODE_H #pragma once -#include -#include -#include +#include "myurl/myosi.h" +#include "myhtml/mystring.h" +#include "myencoding/encoding.h" #ifdef __cplusplus extern "C" { diff --git a/include/myurl/scheme.h b/include/myurl/scheme.h index 7d75770..dca97d6 100644 --- a/include/myurl/scheme.h +++ b/include/myurl/scheme.h @@ -22,9 +22,9 @@ #define MyURL_SCHEME_H #pragma once -#include -#include -#include +#include "myurl/myosi.h" +#include "myurl/scheme_const.h" +#include "mycore/utils.h" #ifdef __cplusplus extern "C" { diff --git a/include/myurl/serialization.h b/include/myurl/serialization.h index fd70d7a..ea25906 100644 --- a/include/myurl/serialization.h +++ b/include/myurl/serialization.h @@ -24,8 +24,8 @@ #include -#include -#include +#include "myurl/myosi.h" +#include "myurl/utils.h" #ifdef __cplusplus extern "C" { diff --git a/include/myurl/url.h b/include/myurl/url.h index 3a194ae..9877299 100644 --- a/include/myurl/url.h +++ b/include/myurl/url.h @@ -22,13 +22,13 @@ #define MyURL_H #pragma once -#include -#include -#include -#include -#include -#include -#include +#include "myurl/myosi.h" +#include "myhtml/mystring.h" +#include "myurl/scheme.h" +#include "myurl/host.h" +#include "myurl/path.h" +#include "myurl/utils.h" +#include "myurl/serialization.h" #ifdef __cplusplus extern "C" { diff --git a/include/myurl/utils.h b/include/myurl/utils.h index 5fe66e5..df5c572 100644 --- a/include/myurl/utils.h +++ b/include/myurl/utils.h @@ -24,9 +24,9 @@ typedef struct myurl_utils_data_list myurl_utils_data_list_t; -#include -#include -#include +#include "myurl/myosi.h" +#include "myurl/parser.h" +#include "myhtml/mystring.h" #include diff --git a/source/modest/Makefile.mk b/source/modest/Makefile.mk index 812bf35..f2e12a1 100644 --- a/source/modest/Makefile.mk +++ b/source/modest/Makefile.mk @@ -1,14 +1,10 @@ -find_files_h = $(wildcard $(SRCDIR)/modest/$(dir)/*.h) -find_files_c = $(wildcard $(SRCDIR)/modest/$(dir)/*.c) +modest_dirs := . finder style node layer render utils +modest_objs := $(call MODEST_UTILS_OBJS,modest,$(modest_dirs)) -SUBDIRS := . finder style node layer render utils -HDRS += $(foreach dir,$(SUBDIRS),$(find_files_h)) -SRCS += $(foreach dir,$(SUBDIRS),$(find_files_c)) +modest_all: $(modest_objs) -modest_clone: MODEST_DIR_$(SUBDIRS) - mkdir -p $(INCLUDE_TMP)/modest - cp $(SRCDIR)/modest/*.h $(INCLUDE_TMP)/modest +modest_clean: + rm -f $(modest_objs) -MODEST_DIR_$(SUBDIRS): - mkdir -p $(INCLUDE_TMP)/modest/$(patsubst MODEST_DIR_%,%,$@) - cp $(SRCDIR)/modest/$(patsubst MODEST_DIR_%,%,$@)/*.h $(INCLUDE_TMP)/modest/$(patsubst MODEST_DIR_%,%,$@)/ +modest_clone: + $(call MODEST_UTILS_HDRS_CLONE,modest,$(modest_dirs)) diff --git a/source/modest/finder/match.c b/source/modest/finder/match.c index 411abe6..5385931 100644 --- a/source/modest/finder/match.c +++ b/source/modest/finder/match.c @@ -82,43 +82,34 @@ bool modest_finder_match_attribute_ws(myhtml_token_attr_t* attr, const char* key if(mycore_strncasecmp(key, attr->key.data, key_len) == 0) { size_t i = 0; + size_t begin; if(attr->value.length >= value_len) { if(case_sensitive) { while(i < attr->value.length) { - size_t end = i + value_len; + begin = i; + while(i < attr->value.length && mycore_utils_whithspace(attr->value.data[i], !=, ||)) {i++;} - if(end > attr->value.length) - return false; - - if( - (mycore_strncmp(value, &attr->value.data[i], value_len) == 0) && - (mycore_utils_whithspace(attr->value.data[end], ==, ||) || end == attr->value.length)) - { + if((i - begin) == value_len && (mycore_strncmp(value, &attr->value.data[begin], value_len) == 0)) { return true; } - - i++; + /* skip all ws */ + while(i < attr->value.length && mycore_utils_whithspace(attr->value.data[i], ==, ||)) {i++;} } } else { while(i < attr->value.length) { - size_t end = i + value_len; + begin = i; + while(i < attr->value.length && mycore_utils_whithspace(attr->value.data[i], !=, ||)) {i++;} - if(end > attr->value.length) - return false; - - if( - (mycore_strncasecmp(value, &attr->value.data[i], value_len) == 0) && - (mycore_utils_whithspace(attr->value.data[end], ==, ||) || end == attr->value.length)) - { + if((i - begin) == value_len && (mycore_strncasecmp(value, &attr->value.data[begin], value_len) == 0)) { return true; } - - i++; + /* skip all ws */ + while(i < attr->value.length && mycore_utils_whithspace(attr->value.data[i], ==, ||)) {i++;} } } } diff --git a/source/modest/finder/thread.c b/source/modest/finder/thread.c index 4ed3ac9..5ce2b21 100644 --- a/source/modest/finder/thread.c +++ b/source/modest/finder/thread.c @@ -59,23 +59,27 @@ mystatus_t modest_finder_thread_init(modest_finder_t* finder, modest_finder_thre return MODEST_STATUS_OK; /* create and init threads */ +#ifdef MyCORE_BUILD_WITHOUT_THREADS + finder_thread->thread = NULL; +#else finder_thread->thread = mythread_create(); if(finder_thread->thread == NULL) return MODEST_STATUS_OK; - mystatus_t status = mythread_init(finder_thread->thread, "lastmac", thread_count); + mystatus_t status = mythread_init(finder_thread->thread, MyTHREAD_TYPE_STREAM, thread_count, 0); if(status) { - mythread_destroy(finder_thread->thread, NULL, true); + mythread_destroy(finder_thread->thread, NULL, NULL, true); return MODEST_STATUS_OK; } finder_thread->thread->context = finder_thread; /* create threads */ - for(size_t i = finder_thread->thread->pth_list_root; i < finder_thread->thread->pth_list_size; i++) { - myhread_create_stream(finder_thread->thread, mythread_function, modest_finder_thread_stream, MyTHREAD_OPT_UNDEF, &status); + for(size_t i = 0; i < finder_thread->thread->entries_size; i++) { + myhread_entry_create(finder_thread->thread, mythread_function, modest_finder_thread_stream, MyTHREAD_OPT_UNDEF); } +#endif return MODEST_STATUS_OK; } @@ -96,15 +100,10 @@ modest_finder_thread_t * modest_finder_thread_destroy(modest_finder_thread_t* fi finder_thread->entry_obj = mcobject_async_destroy(finder_thread->entry_obj, true); finder_thread->declaration_obj = mcobject_async_destroy(finder_thread->declaration_obj, true); - if(finder_thread->thread) { - finder_thread->thread->stream_opt = MyTHREAD_OPT_QUIT; - - for(size_t i = finder_thread->thread->pth_list_root; i < finder_thread->thread->pth_list_size; i++) { - finder_thread->thread->pth_list[i].data.opt = MyTHREAD_OPT_QUIT; - } - - finder_thread->thread = mythread_destroy(finder_thread->thread, NULL, true); - } +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(finder_thread->thread) + finder_thread->thread = mythread_destroy(finder_thread->thread, mythread_callback_quit, NULL, true); +#endif if(finder_thread->context_list) { mycore_free(finder_thread->context_list); @@ -133,6 +132,7 @@ void modest_finder_thread_collate_node(modest_t* modest, myhtml_tree_node_t* nod } } +#ifndef MyCORE_BUILD_WITHOUT_THREADS mystatus_t modest_finder_thread_process(modest_t* modest, modest_finder_thread_t* finder_thread, myhtml_tree_node_t* scope_node, mycss_selectors_list_t* selector_list) { @@ -142,7 +142,7 @@ mystatus_t modest_finder_thread_process(modest_t* modest, modest_finder_thread_t if(finder_thread->finder == NULL) return MODEST_STATUS_ERROR; - mythread_resume_all(finder_thread->thread); + mythread_resume(finder_thread->thread); modest_finder_thread_wait_for_all_done(finder_thread); /* calc result */ @@ -151,7 +151,7 @@ mystatus_t modest_finder_thread_process(modest_t* modest, modest_finder_thread_t /* compare results */ while(node) { - for(size_t i = finder_thread->thread->pth_list_root; i < finder_thread->thread->pth_list_size; i++) + for(size_t i = 0; i < finder_thread->thread->entries_length; i++) { modest_finder_thread_context_t* context = &context_list[i]; modest_finder_thread_entry_t* entry = context->entry; @@ -194,19 +194,16 @@ mystatus_t modest_finder_thread_process(modest_t* modest, modest_finder_thread_t void modest_finder_thread_wait_for_all_done(modest_finder_thread_t* finder_thread) { - const struct timespec tomeout = {0, 0}; - - for (size_t idx = finder_thread->thread->pth_list_root; idx < finder_thread->thread->pth_list_size; idx++) { - while((finder_thread->thread->pth_list[idx].data.opt & MyTHREAD_OPT_DONE) == 0) { - mycore_thread_nanosleep(&tomeout); + for (size_t idx = 0; idx < finder_thread->thread->entries_length; idx++) { + while((finder_thread->thread->entries[idx].context.opt & MyTHREAD_OPT_DONE) == 0) { + mythread_nanosleep_sleep(finder_thread->thread->timespec); } } } +#endif /* if undef MyCORE_BUILD_WITHOUT_THREADS */ modest_finder_thread_context_t * modest_finder_thread_create_context(modest_finder_thread_t* finder_thread, size_t count) { - /* +1 because threads ids begin 1 */ - count++; finder_thread->context_list_size = count; modest_finder_thread_context_t *ctx = mycore_calloc(count, sizeof(modest_finder_thread_context_t)); @@ -216,7 +213,7 @@ modest_finder_thread_context_t * modest_finder_thread_create_context(modest_find mcobject_async_status_t mcstatus; - for(size_t i = 1; i < count; i++) { + for(size_t i = 0; i < count; i++) { ctx[i].entry_node_id = mcobject_async_node_add(finder_thread->entry_obj, &mcstatus); if(mcstatus) { @@ -230,7 +227,7 @@ modest_finder_thread_context_t * modest_finder_thread_create_context(modest_find } } - for(size_t i = 1; i < count; i++) { + for(size_t i = 0; i < count; i++) { ctx[i].declaration_node_id = mcobject_async_node_add(finder_thread->declaration_obj, &mcstatus); if(mcstatus) { @@ -371,6 +368,7 @@ void modest_finder_thread_callback_found(modest_finder_t* finder, myhtml_tree_no } } +#ifndef MyCORE_BUILD_WITHOUT_THREADS void modest_finder_thread_stream(mythread_id_t thread_id, void* arg) { mythread_context_t* ctx = (mythread_context_t*)arg; @@ -380,7 +378,7 @@ void modest_finder_thread_stream(mythread_id_t thread_id, void* arg) modest_finder_thread_found_context_t found_ctx = {finder_thread, &finder_thread->context_list[ctx->id]}; size_t count = 0, counnt_done = ctx->id - 1; - size_t offset = (ctx->mythread->pth_list_size - 1); + size_t offset = (ctx->mythread->entries_size - 1); while(selector_list) { for(size_t i = 0; i < selector_list->entries_list_length; i++) { @@ -403,5 +401,5 @@ void modest_finder_thread_stream(mythread_id_t thread_id, void* arg) ctx->opt = MyTHREAD_OPT_STOP|MyTHREAD_OPT_DONE; } - +#endif diff --git a/source/modest/finder/thread.h b/source/modest/finder/thread.h index b7965cb..1e9b82e 100644 --- a/source/modest/finder/thread.h +++ b/source/modest/finder/thread.h @@ -29,7 +29,7 @@ #include "modest/finder/myosi.h" #include "modest/finder/finder.h" -#include "mycore/thread.h" +#include "mycore/mythread.h" #include "mycore/utils/mcobject_async.h" #include "mycss/declaration/myosi.h" diff --git a/source/modest/modest.c b/source/modest/modest.c index 7d86054..8983b86 100644 --- a/source/modest/modest.c +++ b/source/modest/modest.c @@ -30,6 +30,8 @@ modest_t * modest_create(void) mystatus_t modest_init(modest_t* modest) { + mystatus_t status; + /* Modest nodes */ modest->mnode_obj = mcobject_async_create(); if(modest->mnode_obj == NULL) @@ -61,12 +63,16 @@ mystatus_t modest_init(modest_t* modest) /* Modest style type */ - modest->mstyle_type_obj = mchar_async_create(12, (4096 * 5)); + modest->mstyle_type_obj = mchar_async_create(); if(modest->mstyle_type_obj == NULL) return MODEST_STATUS_ERROR_STYLE_TYPE_CREATE; - modest->mstyle_type_node_id = mchar_async_node_add(modest->mstyle_type_obj); + if((status = mchar_async_init(modest->mstyle_type_obj, 12, (4096 * 5)))) + return status; + modest->mstyle_type_node_id = mchar_async_node_add(modest->mstyle_type_obj, &status); + if(status) + return status; /* for raw declaration style */ modest->mraw_style_declaration_obj = mcobject_create(); diff --git a/source/mycore/Makefile.mk b/source/mycore/Makefile.mk index 039235f..4156566 100644 --- a/source/mycore/Makefile.mk +++ b/source/mycore/Makefile.mk @@ -1,14 +1,10 @@ -find_files_h = $(wildcard $(SRCDIR)/mycore/$(dir)/*.h) -find_files_c = $(wildcard $(SRCDIR)/mycore/$(dir)/*.c) +mycore_dirs := . utils +mycore_objs := $(call MODEST_UTILS_OBJS,mycore,$(mycore_dirs)) -SUBDIRS := . utils -HDRS += $(foreach dir,$(SUBDIRS),$(find_files_h)) -SRCS += $(foreach dir,$(SUBDIRS),$(find_files_c)) +mycore_all: $(mycore_objs) -mycore_clone: MyCORE_DIR_$(SUBDIRS) - mkdir -p $(INCLUDE_TMP)/mycore/utils - cp $(SRCDIR)/mycore/utils/*.h $(INCLUDE_TMP)/mycore/utils +mycore_clean: + rm -f $(mycore_objs) -MyCORE_DIR_$(SUBDIRS): - mkdir -p $(INCLUDE_TMP)/mycore/$(patsubst MyCORE_DIR_%,%,$@) - cp $(SRCDIR)/mycore/$(patsubst MyCORE_DIR_%,%,$@)/*.h $(INCLUDE_TMP)/mycore/$(patsubst MyCORE_DIR_%,%,$@)/ +mycore_clone: + $(call MODEST_UTILS_HDRS_CLONE,mycore,$(mycore_dirs)) diff --git a/source/mycore/myosi.c b/source/mycore/myosi.c index d5e121e..f9758ed 100644 --- a/source/mycore/myosi.c +++ b/source/mycore/myosi.c @@ -20,10 +20,3 @@ #include "mycore/myosi.h" -void mycore_print(FILE* out, const char* format, ...) -{ - va_list argptr; - va_start(argptr, format); - vfprintf(out, format, argptr); - va_end(argptr); -} diff --git a/source/mycore/myosi.h b/source/mycore/myosi.h index 72c2dc2..b96433f 100644 --- a/source/mycore/myosi.h +++ b/source/mycore/myosi.h @@ -27,12 +27,14 @@ #include #include #include -#include +#include #define MyCORE_VERSION_MAJOR 1 #define MyCORE_VERSION_MINOR 0 #define MyCORE_VERSION_PATCH 0 +#define MyCORE_BUILD_WITHOUT_THREADS + #ifdef __cplusplus //extern "C" { #endif @@ -60,14 +62,14 @@ /* Debug */ #ifdef MyCORE_DEBUG_MODE #define MyCORE_DEBUG(format, ...) \ - mycore_print(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) + mycore_fprintf(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) #else #define MyCORE_DEBUG(format, ...) #endif #ifdef MyCORE_DEBUG_MODE #define MyCORE_DEBUG_ERROR(format, ...) \ - mycore_print(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) + mycore_fprintf(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) #else #define MyCORE_DEBUG_ERROR(format, ...) #endif @@ -123,22 +125,16 @@ enum mycore_status { MyCORE_STATUS_MCOBJECT_ERROR_CACHE_CREATE = 0x0055, MyCORE_STATUS_MCOBJECT_ERROR_CHUNK_CREATE = 0x0056, MyCORE_STATUS_MCOBJECT_ERROR_CHUNK_INIT = 0x0057, - MyCORE_STATUS_MCOBJECT_ERROR_CACHE_REALLOC = 0x0058 + MyCORE_STATUS_MCOBJECT_ERROR_CACHE_REALLOC = 0x0058, + MyCORE_STATUS_ASYNC_ERROR_LOCK = 0x0060, + MyCORE_STATUS_ASYNC_ERROR_UNLOCK = 0x0061, + MyCORE_STATUS_ERROR_NO_FREE_SLOT = 0x0062, } typedef mycore_status_t; typedef unsigned int mystatus_t; /* thread */ -enum mythread_thread_opt { - MyTHREAD_OPT_UNDEF = 0x00, - MyTHREAD_OPT_WAIT = 0x01, - MyTHREAD_OPT_QUIT = 0x02, - MyTHREAD_OPT_STOP = 0x04, - MyTHREAD_OPT_DONE = 0x08 -} -typedef mythread_thread_opt_t; - typedef struct mythread_queue_list_entry mythread_queue_list_entry_t; typedef struct mythread_queue_thread_param mythread_queue_thread_param_t; typedef struct mythread_queue_list mythread_queue_list_t; @@ -146,9 +142,8 @@ typedef struct mythread_queue_node mythread_queue_node_t; typedef struct mythread_queue mythread_queue_t; typedef size_t mythread_id_t; -typedef struct mythread_workers_list mythread_workers_list_t; typedef struct mythread_context mythread_context_t; -typedef struct mythread_list mythread_list_t; +typedef struct mythread_entry mythread_entry_t; typedef struct mythread mythread_t; /* mystring */ @@ -164,9 +159,28 @@ typedef void (*mycore_callback_serialize_f)(const char* buffer, size_t size, voi void * mycore_malloc(size_t size); void * mycore_realloc(void* dst, size_t size); void * mycore_calloc(size_t num, size_t size); -void mycore_free(void* dst); +void * mycore_free(void* dst); + +/* io */ +int mycore_printf(const char* format, ...); +int mycore_fprintf(FILE* out, const char* format, ...); +int mycore_snprintf(char* buffer, size_t buffer_size, const char* format, ...); + +/** + * Platform-specific hdef performance clock queries. + * Implemented in perf.c + */ + +/** Get clock resolution */ +uint64_t mycore_hperf_res(mystatus_t *status); + +/** Get current value in clock ticks */ +uint64_t mycore_hperf_clock(mystatus_t *status); + +/** Print an hperf measure */ +mystatus_t mycore_hperf_print(const char *name, uint64_t x, uint64_t y, FILE *fh); +mystatus_t mycore_hperf_print_by_val(const char *name, uint64_t x, FILE *fh); -void mycore_print(FILE* out, const char* format, ...); #ifdef __cplusplus } /* extern "C" */ diff --git a/source/mycore/mythread.c b/source/mycore/mythread.c new file mode 100644 index 0000000..c78e0ae --- /dev/null +++ b/source/mycore/mythread.c @@ -0,0 +1,335 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/mythread.h" + +#ifndef MyCORE_BUILD_WITHOUT_THREADS + +mythread_t * mythread_create(void) +{ + return mycore_calloc(1, sizeof(mythread_t)); +} + +mystatus_t mythread_init(mythread_t *mythread, mythread_type_t type, size_t threads_count, size_t id_increase) +{ + if(threads_count == 0) + return MyCORE_STATUS_ERROR; + + mythread->entries_size = threads_count; + mythread->entries_length = 0; + mythread->id_increase = id_increase; + mythread->type = type; + + mythread->entries = (mythread_entry_t*)mycore_calloc(mythread->entries_size, sizeof(mythread_entry_t)); + if(mythread->entries == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + mythread->attr = mythread_thread_attr_init(mythread); + if(mythread->attr == NULL) + return MyCORE_STATUS_THREAD_ERROR_ATTR_INIT; + + mythread->timespec = mythread_nanosleep_create(mythread); + if(mythread->timespec == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + return MyCORE_STATUS_OK; +} + +void mythread_clean(mythread_t *mythread) +{ + mythread_thread_attr_clean(mythread, mythread->attr); + mythread_nanosleep_clean(mythread->timespec); + + mythread->sys_last_error = 0; +} + +mythread_t * mythread_destroy(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx, bool self_destroy) +{ + if(mythread == NULL) + return NULL; + + if(mythread->entries) { + mythread_resume(mythread); + mythread_quit(mythread, before_join, ctx); + mycore_free(mythread->entries); + } + + mythread_thread_attr_destroy(mythread, mythread->attr); + mythread_nanosleep_destroy(mythread->timespec); + + if(self_destroy) { + mycore_free(mythread); + return NULL; + } + + return mythread; +} + +mystatus_t myhread_entry_create(mythread_t *mythread, mythread_process_f process_func, mythread_work_f work_func, mythread_thread_opt_t opt) +{ + mythread->sys_last_error = 0; + + if(mythread->entries_length >= mythread->entries_size) + return MyCORE_STATUS_THREAD_ERROR_NO_SLOTS; + + mythread_entry_t *entry = &mythread->entries[mythread->entries_length]; + + entry->context.mythread = mythread; + entry->context.func = work_func; + entry->context.id = mythread->entries_length; + entry->context.t_count = mythread->entries_size; + entry->context.opt = opt; + entry->context.status = 0; + + entry->context.timespec = mythread_nanosleep_create(mythread); + if(entry->context.timespec == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + entry->context.mutex = mythread_mutex_create(mythread); + if(entry->context.mutex == NULL) + return MyCORE_STATUS_THREAD_ERROR_MUTEX_INIT; + + if(mythread_mutex_wait(mythread, entry->context.mutex)) { + mythread_mutex_close(mythread, entry->context.mutex); + return MyCORE_STATUS_THREAD_ERROR_MUTEX_LOCK; + } + + entry->thread = mythread_thread_create(mythread, process_func, &entry->context); + if(entry->thread == NULL) { + mythread_mutex_close(mythread, entry->context.mutex); + return MyCORE_STATUS_ERROR; + } + + mythread->entries_length++; + + return MyCORE_STATUS_OK; +} + +mythread_id_t myhread_increase_id_by_entry_id(mythread_t* mythread, mythread_id_t thread_id) +{ + return mythread->id_increase + thread_id; +} + +/* + * Global functions, for all threads + */ +mystatus_t mythread_join(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx) +{ + for (size_t i = 0; i < mythread->entries_length; i++) { + if(before_join) + before_join(mythread, &mythread->entries[i], ctx); + + if(mythread_thread_join(mythread, mythread->entries[i].thread)) + return MyCORE_STATUS_ERROR; + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_quit(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx) +{ + mythread_option_set(mythread, MyTHREAD_OPT_QUIT); + + for (size_t i = 0; i < mythread->entries_length; i++) + { + if(before_join) + before_join(mythread, &mythread->entries[i], ctx); + + if(mythread_thread_join(mythread, mythread->entries[i].thread) || + mythread_thread_destroy(mythread, mythread->entries[i].thread)) + { + return MyCORE_STATUS_ERROR; + } + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_stop(mythread_t *mythread) +{ + if(mythread->opt & MyTHREAD_OPT_STOP) + return MyCORE_STATUS_OK; + + mythread_option_set(mythread, MyTHREAD_OPT_STOP); + + for (size_t i = 0; i < mythread->entries_length; i++) + { + while(mythread->entries[i].context.opt != MyTHREAD_OPT_STOP) { + mythread_nanosleep_sleep(mythread->timespec); + } + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_suspend(mythread_t *mythread) +{ + if(mythread->opt & MyTHREAD_OPT_WAIT) + return MyCORE_STATUS_OK; + + mythread_option_set(mythread, MyTHREAD_OPT_WAIT); + + for (size_t i = 0; i < mythread->entries_length; i++) + { + while(mythread->entries[i].context.opt != MyTHREAD_OPT_STOP && + mythread->entries[i].context.opt != MyTHREAD_OPT_WAIT) + { + mythread_nanosleep_sleep(mythread->timespec); + } + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_resume(mythread_t *mythread) +{ + if(mythread->opt & MyTHREAD_OPT_WAIT) { + mythread_option_set(mythread, MyTHREAD_OPT_UNDEF); + return MyCORE_STATUS_OK; + } + + mythread_option_set(mythread, MyTHREAD_OPT_UNDEF); + + for (size_t i = 0; i < mythread->entries_length; i++) + { + if(mythread->entries[i].context.opt == MyTHREAD_OPT_STOP) { + mythread->entries[i].context.opt = MyTHREAD_OPT_UNDEF; + + if(mythread_mutex_post(mythread, mythread->entries[i].context.mutex)) + return MyCORE_STATUS_ERROR; + } + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_check_status(mythread_t *mythread) +{ + for (size_t i = 0; i < mythread->entries_length; i++) + { + if(mythread->entries[i].context.status) + return mythread->entries[i].context.status; + } + + return MyCORE_STATUS_OK; +} + +mythread_thread_opt_t mythread_option(mythread_t *mythread) +{ + return mythread->opt; +} + +void mythread_option_set(mythread_t *mythread, mythread_thread_opt_t opt) +{ + mythread->opt = opt; +} + +/* + * Entries functions, for all threads + */ +mystatus_t mythread_entry_join(mythread_entry_t* entry, mythread_callback_before_entry_join_f before_join, void* ctx) +{ + if(before_join) + before_join(entry->context.mythread, entry, ctx); + + if(mythread_thread_join(entry->context.mythread, entry->thread)) + return MyCORE_STATUS_ERROR; + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_entry_quit(mythread_entry_t* entry, mythread_callback_before_entry_join_f before_join, void* ctx) +{ + if(before_join) + before_join(entry->context.mythread, entry, ctx); + + if(mythread_thread_join(entry->context.mythread, entry->thread) || + mythread_thread_destroy(entry->context.mythread, entry->thread)) + { + return MyCORE_STATUS_ERROR; + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_entry_stop(mythread_entry_t* entry) +{ + if(entry->context.opt & MyTHREAD_OPT_STOP) + return MyCORE_STATUS_OK; + + entry->context.opt = MyTHREAD_OPT_STOP; + + while(entry->context.opt != MyTHREAD_OPT_STOP) { + mythread_nanosleep_sleep(entry->context.mythread->timespec); + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_entry_suspend(mythread_entry_t* entry) +{ + if(entry->context.opt & MyTHREAD_OPT_WAIT) + return MyCORE_STATUS_OK; + + entry->context.opt = MyTHREAD_OPT_WAIT; + + while(entry->context.opt != MyTHREAD_OPT_STOP && entry->context.opt != MyTHREAD_OPT_WAIT) { + mythread_nanosleep_sleep(entry->context.mythread->timespec); + } + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_entry_resume(mythread_entry_t* entry) +{ + if(entry->context.opt & MyTHREAD_OPT_WAIT) { + entry->context.opt = MyTHREAD_OPT_UNDEF; + } + else if(entry->context.opt == MyTHREAD_OPT_STOP) { + entry->context.opt = MyTHREAD_OPT_UNDEF; + + if(mythread_mutex_post(entry->context.mythread, entry->context.mutex)) + return MyCORE_STATUS_ERROR; + } + else + entry->context.opt = MyTHREAD_OPT_UNDEF; + + return MyCORE_STATUS_OK; +} + +mystatus_t mythread_entry_status(mythread_entry_t* entry) +{ + return entry->context.status; +} + +mythread_t * mythread_entry_mythread(mythread_entry_t* entry) +{ + return entry->context.mythread; +} + +/* Callbacks */ +void mythread_callback_quit(mythread_t* mythread, mythread_entry_t* entry, void* ctx) +{ + while(entry->context.opt != MyTHREAD_OPT_QUIT) + mythread_nanosleep_sleep(mythread->timespec); +} + +#endif + diff --git a/source/mycore/mythread.h b/source/mycore/mythread.h new file mode 100644 index 0000000..c44ac47 --- /dev/null +++ b/source/mycore/mythread.h @@ -0,0 +1,159 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#ifndef MyCORE_THREAD_H +#define MyCORE_THREAD_H +#pragma once + +#ifdef __cplusplus +//extern "C" { +#endif + +#include "mycore/myosi.h" +#include "mycore/mystring.h" + +#ifdef MyCORE_BUILD_WITHOUT_THREADS + +struct mythread { + int sys_last_error; +}; + +#else +/* functions */ +typedef void (*mythread_callback_before_entry_join_f)(mythread_t* mythread, mythread_entry_t* entry, void* ctx); +typedef void (*mythread_process_f)(void* arg); +typedef void (*mythread_work_f)(mythread_id_t thread_id, void* arg); + +void mythread_function_queue_stream(void *arg); +void mythread_function_queue_batch(void *arg); +void mythread_function(void *arg); + +enum mythread_thread_opt { + MyTHREAD_OPT_UNDEF = 0x00, + MyTHREAD_OPT_WAIT = 0x01, + MyTHREAD_OPT_QUIT = 0x02, + MyTHREAD_OPT_STOP = 0x04, + MyTHREAD_OPT_DONE = 0x08 +} +typedef mythread_thread_opt_t; + +enum mythread_type { + MyTHREAD_TYPE_STREAM = 0x00, + MyTHREAD_TYPE_BATCH = 0x01 +} +typedef mythread_type_t; + +// thread +struct mythread_context { + mythread_id_t id; + mythread_work_f func; + + volatile size_t t_count; + volatile mythread_thread_opt_t opt; + + mystatus_t status; + + void* mutex; + void* timespec; + mythread_t* mythread; +}; + +struct mythread_entry { + void* thread; + + mythread_context_t context; + mythread_process_f process_func; +}; + +struct mythread { + mythread_entry_t *entries; + size_t entries_length; + size_t entries_size; + size_t id_increase; + + void* context; + void* attr; + void* timespec; + + int sys_last_error; + + mythread_type_t type; + volatile mythread_thread_opt_t opt; +}; + +mythread_t * mythread_create(void); +mystatus_t mythread_init(mythread_t *mythread, mythread_type_t type, size_t threads_count, size_t id_increase); +void mythread_clean(mythread_t *mythread); +mythread_t * mythread_destroy(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx, bool self_destroy); + +mythread_id_t myhread_increase_id_by_entry_id(mythread_t* mythread, mythread_id_t thread_id); + +/* set for all threads */ +mystatus_t mythread_join(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_quit(mythread_t *mythread, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_stop(mythread_t *mythread); +mystatus_t mythread_resume(mythread_t *mythread); +mystatus_t mythread_suspend(mythread_t *mythread); +mystatus_t mythread_check_status(mythread_t *mythread); + +mythread_thread_opt_t mythread_option(mythread_t *mythread); +void mythread_option_set(mythread_t *mythread, mythread_thread_opt_t opt); + +/* Entries */ +mystatus_t myhread_entry_create(mythread_t *mythread, mythread_process_f process_func, mythread_work_f func, mythread_thread_opt_t opt); + +mystatus_t mythread_entry_join(mythread_entry_t* entry, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_entry_quit(mythread_entry_t* entry, mythread_callback_before_entry_join_f before_join, void* ctx); +mystatus_t mythread_entry_stop(mythread_entry_t* entry); +mystatus_t mythread_entry_resume(mythread_entry_t* entry); +mystatus_t mythread_entry_suspend(mythread_entry_t* entry); +mystatus_t mythread_entry_status(mythread_entry_t* entry); +mythread_t * mythread_entry_mythread(mythread_entry_t* entry); + +/* API for ports */ +void * mythread_thread_create(mythread_t *mythread, void* process_func, void* ctx); +mystatus_t mythread_thread_join(mythread_t *mythread, void* thread); +mystatus_t mythread_thread_cancel(mythread_t *mythread, void* thread); +mystatus_t mythread_thread_destroy(mythread_t *mythread, void* thread); + +void * mythread_thread_attr_init(mythread_t *mythread); +void mythread_thread_attr_clean(mythread_t *mythread, void* attr); +void mythread_thread_attr_destroy(mythread_t *mythread, void* attr); + +void * mythread_mutex_create(mythread_t *mythread); +mystatus_t mythread_mutex_post(mythread_t *mythread, void* mutex); +mystatus_t mythread_mutex_wait(mythread_t *mythread, void* mutex); +void mythread_mutex_close(mythread_t *mythread, void* mutex); + +void * mythread_nanosleep_create(mythread_t* mythread); +void mythread_nanosleep_clean(void* timespec); +void mythread_nanosleep_destroy(void* timespec); +mystatus_t mythread_nanosleep_sleep(void* timespec); + +/* callback */ +void mythread_callback_quit(mythread_t* mythread, mythread_entry_t* entry, void* ctx); + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* MyCORE_THREAD_H */ diff --git a/source/mycore/thread.c b/source/mycore/thread.c deleted file mode 100644 index 5ccd27c..0000000 --- a/source/mycore/thread.c +++ /dev/null @@ -1,1185 +0,0 @@ -/* - Copyright (C) 2015-2017 Alexander Borisov - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - Author: lex.borisov@gmail.com (Alexander Borisov) -*/ - -#include "mycore/thread.h" - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - -#if defined(IS_OS_WINDOWS) -/*********************************************************************************** - * - * For Windows - * - ***********************************************************************************/ -mystatus_t mycore_thread_create(mythread_t *mythread, mythread_list_t *thr, void *work_func) -{ - thr->pth = CreateThread(NULL, // default security attributes - 0, // use default stack size - work_func, // thread function name - &thr->data, // argument to thread function - 0, // use default creation flags - NULL); // returns the thread identifier - - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_join(mythread_t *mythread, mythread_list_t *thr) -{ - WaitForSingleObject(thr->pth, INFINITE); - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_cancel(mythread_t *mythread, mythread_list_t *thr) -{ - TerminateThread(thr->pth, 0); - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_attr_init(mythread_t *mythread) -{ - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_attr_clean(mythread_t *mythread) -{ - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_attr_destroy(mythread_t *mythread) -{ - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_create(mythread_t *mythread, mythread_context_t *ctx, size_t prefix_id) -{ - ctx->mutex = CreateSemaphore(NULL, 0, 1, NULL); - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_post(mythread_t *mythread, mythread_context_t *ctx) -{ - ReleaseSemaphore(ctx->mutex, 1, NULL); - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_wait(mythread_t *mythread, mythread_context_t *ctx) -{ - WaitForSingleObject(ctx->mutex, INFINITE); - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_try_wait(mythread_t *mythread, mythread_context_t *ctx) -{ - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_close(mythread_t *mythread, mythread_context_t *ctx) -{ - CloseHandle(ctx->mutex); - - return MyCORE_STATUS_OK; -} - -void mycore_thread_nanosleep(const struct timespec *tomeout) -{ - Sleep(0); -} - -#else /* defined(IS_OS_WINDOWS) */ -/*********************************************************************************** - * - * For all unix system. POSIX pthread - * - ***********************************************************************************/ - -mystatus_t mycore_thread_create(mythread_t *mythread, mythread_list_t *thr, void *work_func) -{ - pthread_create(&thr->pth, mythread->attr, - work_func, - (void*)(&thr->data)); - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_join(mythread_t *mythread, mythread_list_t *thr) -{ - pthread_join(thr->pth, NULL); - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_cancel(mythread_t *mythread, mythread_list_t *thr) -{ - pthread_cancel(thr->pth); - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_attr_init(mythread_t *mythread) -{ - mythread->attr = (pthread_attr_t*)mycore_calloc(1, sizeof(pthread_attr_t)); - - if(mythread->attr == NULL) - return MyCORE_STATUS_THREAD_ERROR_ATTR_MALLOC; - - mythread->sys_last_error = pthread_attr_init(mythread->attr); - if(mythread->sys_last_error) - return MyCORE_STATUS_THREAD_ERROR_ATTR_INIT; - - mythread->sys_last_error = pthread_attr_setdetachstate(mythread->attr, PTHREAD_CREATE_JOINABLE); - if(mythread->sys_last_error) - return MyCORE_STATUS_THREAD_ERROR_ATTR_SET; - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_attr_clean(mythread_t *mythread) -{ - mythread->attr = NULL; - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_thread_attr_destroy(mythread_t *mythread) -{ - if(mythread->attr) { - mythread->sys_last_error = pthread_attr_destroy(mythread->attr); - - mycore_free(mythread->attr); - mythread->attr = NULL; - - if(mythread->sys_last_error) - return MyCORE_STATUS_THREAD_ERROR_ATTR_DESTROY; - } - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_create(mythread_t *mythread, mythread_context_t *ctx, size_t prefix_id) -{ - ctx->mutex = (pthread_mutex_t*)mycore_calloc(1, sizeof(pthread_mutex_t)); - - if(ctx->mutex == NULL) - return MyCORE_STATUS_THREAD_ERROR_MUTEX_MALLOC; - - if(pthread_mutex_init(ctx->mutex, NULL)) { - mythread->sys_last_error = errno; - return MyCORE_STATUS_THREAD_ERROR_MUTEX_INIT; - } - - if(pthread_mutex_lock(ctx->mutex)) { - mythread->sys_last_error = errno; - return MyCORE_STATUS_THREAD_ERROR_MUTEX_LOCK; - } - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_post(mythread_t *mythread, mythread_context_t *ctx) -{ - if(pthread_mutex_unlock(ctx->mutex)) { - mythread->sys_last_error = errno; - return MyCORE_STATUS_THREAD_ERROR_MUTEX_UNLOCK; - } - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_wait(mythread_t *mythread, mythread_context_t *ctx) -{ - if(pthread_mutex_lock(ctx->mutex)) { - mythread->sys_last_error = errno; - return MyCORE_STATUS_THREAD_ERROR_MUTEX_LOCK; - } - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_try_wait(mythread_t *mythread, mythread_context_t *ctx) -{ - if(pthread_mutex_trylock(ctx->mutex)) { - mythread->sys_last_error = errno; - return MyCORE_STATUS_THREAD_ERROR_MUTEX_LOCK; - } - - return MyCORE_STATUS_OK; -} - -mystatus_t mycore_hread_mutex_close(mythread_t *mythread, mythread_context_t *ctx) -{ - if(ctx->mutex) { - pthread_mutex_destroy(ctx->mutex); - mycore_free(ctx->mutex); - - ctx->mutex = NULL; - } - - return MyCORE_STATUS_OK; -} - -void mycore_thread_nanosleep(const struct timespec *tomeout) -{ - nanosleep(tomeout, NULL); -} - -#endif /* !defined(IS_OS_WINDOWS) */ -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -/* - * - * MyTHREAD logic - * - */ - -mythread_t * mythread_create(void) -{ - return mycore_calloc(1, sizeof(mythread_t)); -} - -#ifdef MyCORE_BUILD_WITHOUT_THREADS - -mystatus_t mythread_init(mythread_t *mythread, const char *sem_prefix, size_t thread_count) -{ - return MyCORE_STATUS_OK; -} - -#else /* MyCORE_BUILD_WITHOUT_THREADS */ - -mystatus_t mythread_init(mythread_t *mythread, const char *sem_prefix, size_t thread_count) -{ - mythread->batch_count = 0; - mythread->batch_first_id = 0; - mythread->stream_opt = MyTHREAD_OPT_STOP; - mythread->batch_opt = MyTHREAD_OPT_STOP; - - if(thread_count) - { - mystatus_t status = mycore_thread_attr_init(mythread); - if(status) - return status; - - mythread->pth_list_root = 1; - mythread->pth_list_length = 1; - mythread->pth_list_size = thread_count + 1; - mythread->pth_list = (mythread_list_t*)mycore_calloc(mythread->pth_list_size, sizeof(mythread_list_t)); - - if(mythread->pth_list == NULL) - return MyCORE_STATUS_THREAD_ERROR_LIST_INIT; - } - else { - mycore_thread_attr_clean(mythread); - - mythread->sys_last_error = 0; - mythread->pth_list_root = 1; - mythread->pth_list_length = 1; - mythread->pth_list_size = 0; - mythread->pth_list = NULL; - } - - if(sem_prefix) - { - mythread->sem_prefix_length = strlen(sem_prefix); - - if(mythread->sem_prefix_length) { - mythread->sem_prefix = mycore_calloc((mythread->sem_prefix_length + 1), sizeof(char)); - - if(mythread->sem_prefix == NULL) { - mythread->sem_prefix_length = 0; - return MyCORE_STATUS_THREAD_ERROR_SEM_PREFIX_MALLOC; - } - - mycore_string_raw_copy(mythread->sem_prefix, sem_prefix, mythread->sem_prefix_length); - } - } - - return MyCORE_STATUS_OK; -} - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -void mythread_clean(mythread_t *mythread) -{ - mythread->sys_last_error = 0; -} - -mythread_t * mythread_destroy(mythread_t *mythread, mythread_callback_before_join_f before_join, bool self_destroy) -{ - if(mythread == NULL) - return NULL; - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - - mycore_thread_attr_destroy(mythread); - - if(mythread->pth_list) { - mythread_resume_all(mythread); - mythread_stream_quit_all(mythread); - mythread_batch_quit_all(mythread); - - if(before_join) - before_join(mythread); - - for (size_t i = mythread->pth_list_root; i < mythread->pth_list_length; i++) - { - mycore_thread_join(mythread, &mythread->pth_list[i]); - } - - mycore_free(mythread->pth_list); - mythread->pth_list = NULL; - } - - if(mythread->sem_prefix) { - mycore_free(mythread->sem_prefix); - - mythread->sem_prefix = NULL; - mythread->sem_prefix_length = 0; - } - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - - if(self_destroy) { - mycore_free(mythread); - return NULL; - } - - return mythread; -} - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - -mythread_id_t _myhread_create_stream_raw(mythread_t *mythread, mythread_work_f work_func, void *process_func, mythread_thread_opt_t opt, mystatus_t *status, size_t total_count) -{ - mythread->sys_last_error = 0; - - if(status) - *status = MyCORE_STATUS_OK; - - if(mythread->pth_list_length >= mythread->pth_list_size) { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_NO_SLOTS; - - return 0; - } - - mythread_list_t *thr = &mythread->pth_list[mythread->pth_list_length]; - - thr->data.mythread = mythread; - thr->data.func = work_func; - thr->data.id = mythread->pth_list_length; - thr->data.t_count = total_count; - thr->data.opt = opt; - thr->data.status = 0; - - mystatus_t m_status = mycore_hread_mutex_create(mythread, &thr->data, 0); - - if(m_status != MyCORE_STATUS_OK && status) { - *status = m_status; - return 0; - } - - m_status = mycore_thread_create(mythread, thr, process_func); - if(m_status != MyCORE_STATUS_OK) - return 0; - - mythread->pth_list_length++; - return thr->data.id; -} - -mythread_id_t myhread_create_stream(mythread_t *mythread, mythread_process_f process_func, mythread_work_f work_func, mythread_thread_opt_t opt, mystatus_t *status) -{ - return _myhread_create_stream_raw(mythread, work_func, process_func, opt, status, 0); -} - -mythread_id_t myhread_create_batch(mythread_t *mythread, mythread_process_f process_func, mythread_work_f work_func, mythread_thread_opt_t opt, mystatus_t *status, size_t count) -{ - if(mythread->batch_count) { - *status = MyCORE_STATUS_THREAD_ERROR_BATCH_INIT; - return 0; - } - else if((mythread->pth_list_length + count) > mythread->pth_list_size) { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_NO_SLOTS; - - return 0; - } - - if(count == 0) - count = 1; - - mythread->batch_first_id = 0; - mythread->batch_count = count; - - size_t start = mythread->pth_list_length; - *status = MyCORE_STATUS_OK; - - bool init_first = false; - - for (size_t i = 0; i < count; i++) - { - mythread_id_t curr_id = _myhread_create_stream_raw(mythread, work_func, process_func, opt, status, i); - - if(init_first == false) { - mythread->batch_first_id = curr_id; - init_first = true; - } - - if(*status) - { - for (size_t n = start; n < (start + i); n++) - { - mythread_list_t *thr = &mythread->pth_list[n]; - - mycore_thread_cancel(mythread, thr); - - mycore_hread_mutex_post(mythread, &thr->data); - mycore_hread_mutex_close(mythread, &thr->data); - } - - mythread->batch_first_id = 0; - mythread->batch_count = 0; - - break; - } - } - - return mythread->batch_first_id; -} - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -// mythread queue functions -#ifndef MyCORE_BUILD_WITHOUT_THREADS -mythread_queue_list_t * mythread_queue_list_create(mystatus_t *status) -{ - if(status) - *status = MyCORE_STATUS_OK; - - mythread_queue_list_t* queue_list = (mythread_queue_list_t*)mycore_calloc(1, sizeof(mythread_queue_list_t)); - - if(queue_list == NULL) { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_MALLOC; - return NULL; - } - - return queue_list; -} - -void mythread_queue_list_destroy(mythread_queue_list_t* queue_list) -{ - if(queue_list == NULL) - return; - - mycore_free(queue_list); -} - -size_t mythread_queue_list_get_count(mythread_queue_list_t* queue_list) -{ - return queue_list->count; -} - -mythread_queue_list_entry_t * mythread_queue_list_entry_push(mythread_t *mythread, mythread_queue_t *queue, mystatus_t *status) -{ - mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; - - if(status) - *status = MyCORE_STATUS_OK; - - mythread_queue_list_entry_t* entry = (mythread_queue_list_entry_t*)mycore_calloc(1, sizeof(mythread_queue_list_entry_t)); - - if(entry == NULL) { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_MALLOC; - return NULL; - } - - entry->thread_param = (mythread_queue_thread_param_t*)mycore_calloc(mythread->pth_list_size, sizeof(mythread_queue_thread_param_t)); - - if(entry->thread_param == NULL) { - mycore_free(entry); - - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_MALLOC; - return NULL; - } - - size_t idx; - for (idx = mythread->batch_first_id; idx < (mythread->batch_first_id + mythread->batch_count); idx++) { - entry->thread_param[idx].use = mythread->pth_list[idx].data.t_count; - } - - entry->queue = queue; - - if(mythread->stream_opt == MyTHREAD_OPT_UNDEF) { - mythread_suspend_all(mythread); - } - else if(mythread->stream_opt == MyTHREAD_OPT_STOP) { - mythread_stop_all(mythread); - } - - if(queue_list->first) { - queue_list->last->next = entry; - entry->prev = queue_list->last; - - queue_list->last = entry; - } - else { - queue_list->first = entry; - queue_list->last = entry; - } - - queue_list->count++; - - if(mythread->stream_opt != MyTHREAD_OPT_STOP) - mythread_resume_all(mythread); - - return entry; -} - -mythread_queue_list_entry_t * mythread_queue_list_entry_delete(mythread_t *mythread, mythread_queue_list_entry_t *entry, bool destroy_queue) -{ - mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; - - mythread_queue_list_entry_t *next = entry->next; - mythread_queue_list_entry_t *prev = entry->prev; - - if(mythread->stream_opt == MyTHREAD_OPT_UNDEF) { - mythread_suspend_all(mythread); - } - else if(mythread->stream_opt == MyTHREAD_OPT_STOP) { - mythread_stop_all(mythread); - } - - if(prev) - prev->next = next; - - if(next) - next->prev = prev; - - if(queue_list->first == entry) - queue_list->first = next; - - if(queue_list->last == entry) - queue_list->last = prev; - - if(mythread->stream_opt != MyTHREAD_OPT_STOP) - mythread_resume_all(mythread); - - if(destroy_queue && entry->queue) - mythread_queue_destroy(entry->queue); - - if(entry->thread_param) - mycore_free(entry->thread_param); - - mycore_free(entry); - - queue_list->count--; - - return NULL; -} - -void mythread_queue_list_entry_clean(mythread_t *mythread, mythread_queue_list_entry_t *entry) -{ - if(entry == NULL) - return; - - mythread_queue_clean(entry->queue); - - size_t idx; - for (idx = mythread->pth_list_root; idx < mythread->batch_first_id; idx++) { - entry->thread_param[idx].use = 0; - } - - for (idx = mythread->batch_first_id; idx < (mythread->batch_first_id + mythread->batch_count); idx++) { - entry->thread_param[idx].use = mythread->pth_list[idx].data.t_count; - } -} - -void mythread_queue_list_entry_wait_for_done(mythread_t *mythread, mythread_queue_list_entry_t *entry) -{ - if(entry == NULL) - return; - - size_t idx; - const struct timespec tomeout = {0, 0}; - - for (idx = mythread->pth_list_root; idx < mythread->pth_list_size; idx++) { - mythread_queue_thread_param_t *thread_param = &entry->thread_param[ idx ]; - while(thread_param->use < entry->queue->nodes_uses) { - mycore_thread_nanosleep(&tomeout); - } - } -} - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -mythread_queue_t * mythread_queue_create(size_t size, mystatus_t *status) -{ - if(status) - *status = MyCORE_STATUS_OK; - - if(size < 4096) - size = 4096; - - mythread_queue_t* queue = (mythread_queue_t*)mycore_malloc(sizeof(mythread_queue_t)); - - if(queue == NULL) { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_MALLOC; - return NULL; - } - - queue->nodes_pos_size = 512; - queue->nodes_size = size; - queue->nodes = (mythread_queue_node_t**)mycore_calloc(queue->nodes_pos_size, sizeof(mythread_queue_node_t*)); - - if(queue->nodes == NULL) { - mycore_free(queue); - - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODES_MALLOC; - return NULL; - } - - mythread_queue_clean(queue); - - queue->nodes[queue->nodes_pos] = (mythread_queue_node_t*)mycore_malloc(sizeof(mythread_queue_node_t) * queue->nodes_size); - - if(queue->nodes[queue->nodes_pos] == NULL) { - mycore_free(queue->nodes); - mycore_free(queue); - - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODE_MALLOC; - return NULL; - } - - return queue; -} - -void mythread_queue_clean(mythread_queue_t* queue) -{ - queue->nodes_length = 0; - queue->nodes_pos = 0; - queue->nodes_root = 0; - queue->nodes_uses = 0; - - if(queue->nodes[queue->nodes_pos]) - mythread_queue_node_clean(&queue->nodes[queue->nodes_pos][queue->nodes_length]); -} - -mythread_queue_t * mythread_queue_destroy(mythread_queue_t* queue) -{ - if(queue == NULL) - return NULL; - - if(queue->nodes) { - for (size_t i = 0; i <= queue->nodes_pos; i++) { - mycore_free(queue->nodes[i]); - } - - mycore_free(queue->nodes); - } - - mycore_free(queue); - - return NULL; -} - -void mythread_queue_node_clean(mythread_queue_node_t* qnode) -{ - memset(qnode, 0, sizeof(mythread_queue_node_t)); -} - -mythread_queue_node_t * mythread_queue_get_prev_node(mythread_queue_node_t* qnode) -{ - return qnode->prev; -} - -mythread_queue_node_t * mythread_queue_get_current_node(mythread_queue_t* queue) -{ - return &queue->nodes[queue->nodes_pos][queue->nodes_length]; -} - -mythread_queue_node_t * mythread_queue_get_first_node(mythread_queue_t* queue) -{ - return &queue->nodes[0][0]; -} - -size_t mythread_queue_count_used_node(mythread_queue_t* queue) -{ - return queue->nodes_uses; -} - -mythread_queue_node_t * mythread_queue_node_malloc(mythread_t *mythread, mythread_queue_t* queue, mystatus_t *status) -{ - queue->nodes_length++; - - if(queue->nodes_length >= queue->nodes_size) - { - queue->nodes_pos++; - - if(queue->nodes_pos >= queue->nodes_pos_size) - { - mythread_queue_wait_all_for_done(mythread); - - queue->nodes_pos_size <<= 1; - mythread_queue_node_t** tmp = mycore_realloc(queue->nodes, sizeof(mythread_queue_node_t*) * queue->nodes_pos_size); - - if(tmp) { - memset(&tmp[queue->nodes_pos], 0, sizeof(mythread_queue_node_t*) * (queue->nodes_pos_size - queue->nodes_pos)); - - queue->nodes = tmp; - } - else { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODES_MALLOC; - - return NULL; - } - } - - if(queue->nodes[queue->nodes_pos] == NULL) { - queue->nodes[queue->nodes_pos] = (mythread_queue_node_t*)mycore_malloc(sizeof(mythread_queue_node_t) * queue->nodes_size); - - if(queue->nodes[queue->nodes_pos] == NULL) { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODE_MALLOC; - - return NULL; - } - } - - queue->nodes_length = 0; - } - - queue->nodes_uses++; - - return &queue->nodes[queue->nodes_pos][queue->nodes_length]; -} - -mythread_queue_node_t * mythread_queue_node_malloc_limit(mythread_t *mythread, mythread_queue_t* queue, size_t limit, mystatus_t *status) -{ - queue->nodes_length++; - - if(queue->nodes_uses >= limit) { - queue->nodes_uses++; - mythread_queue_wait_all_for_done(mythread); - - queue->nodes_length = 0; - queue->nodes_pos = 0; - queue->nodes_root = 0; - queue->nodes_uses = 0; - } - else if(queue->nodes_length >= queue->nodes_size) - { - queue->nodes_pos++; - - if(queue->nodes_pos >= queue->nodes_pos_size) - { - mythread_queue_wait_all_for_done(mythread); - - queue->nodes_pos_size <<= 1; - mythread_queue_node_t** tmp = mycore_realloc(queue->nodes, sizeof(mythread_queue_node_t*) * queue->nodes_pos_size); - - if(tmp) { - memset(&tmp[queue->nodes_pos], 0, sizeof(mythread_queue_node_t*) * (queue->nodes_pos_size - queue->nodes_pos)); - - queue->nodes = tmp; - } - else { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODES_MALLOC; - - return NULL; - } - } - - if(queue->nodes[queue->nodes_pos] == NULL) { - queue->nodes[queue->nodes_pos] = (mythread_queue_node_t*)mycore_malloc(sizeof(mythread_queue_node_t) * queue->nodes_size); - - if(queue->nodes[queue->nodes_pos] == NULL) { - if(status) - *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODE_MALLOC; - - return NULL; - } - } - - queue->nodes_length = 0; - } - - queue->nodes_uses++; - - return &queue->nodes[queue->nodes_pos][queue->nodes_length]; -} - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - -mythread_queue_node_t * mythread_queue_node_malloc_round(mythread_t *mythread, mythread_queue_list_entry_t *entry, mystatus_t *status) -{ - mythread_queue_t* queue = entry->queue; - - queue->nodes_length++; - - if(queue->nodes_length >= queue->nodes_size) { - queue->nodes_uses++; - - mythread_queue_list_entry_wait_for_done(mythread, entry); - mythread_queue_list_entry_clean(mythread, entry); - } - else - queue->nodes_uses++; - - return &queue->nodes[queue->nodes_pos][queue->nodes_length]; -} - -void mythread_queue_wait_all_for_done(mythread_t *mythread) -{ - const struct timespec tomeout = {0, 0}; - - mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; - mythread_queue_list_entry_t *entry = queue_list->first; - - while(entry) - { - for (size_t idx = mythread->pth_list_root; idx < mythread->pth_list_size; idx++) { - while(entry->thread_param[idx].use < entry->queue->nodes_uses) { - mycore_thread_nanosleep(&tomeout); - } - } - - entry = entry->next; - } -} - -#else - -void mythread_queue_wait_all_for_done(mythread_t *mythread) {} - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -#ifdef MyCORE_BUILD_WITHOUT_THREADS - -void mythread_stream_quit_all(mythread_t *mythread) {} -void mythread_batch_quit_all(mythread_t *mythread) {} -void mythread_stream_stop_all(mythread_t *mythread) {} -void mythread_batch_stop_all(mythread_t *mythread) {} -void mythread_stop_all(mythread_t *mythread) {} -void mythread_resume_all(mythread_t *mythread) {} -void mythread_suspend_all(mythread_t *mythread) {} - -#else /* MyCORE_BUILD_WITHOUT_THREADS */ - -// mythread functions -void mythread_stream_quit_all(mythread_t *mythread) -{ - mythread->stream_opt = MyTHREAD_OPT_QUIT; -} - -void mythread_batch_quit_all(mythread_t *mythread) -{ - mythread->batch_opt = MyTHREAD_OPT_QUIT; -} - -void mythread_stream_stop_all(mythread_t *mythread) -{ - if(mythread->stream_opt != MyTHREAD_OPT_STOP) - mythread->stream_opt = MyTHREAD_OPT_STOP; - - size_t idx; - const struct timespec tomeout = {0, 0}; - - for (idx = mythread->pth_list_root; idx < mythread->batch_first_id; idx++) { - while(mythread->pth_list[idx].data.opt != MyTHREAD_OPT_STOP) { - mycore_thread_nanosleep(&tomeout); - } - } -} - -void mythread_batch_stop_all(mythread_t *mythread) -{ - if(mythread->batch_opt != MyTHREAD_OPT_STOP) - mythread->batch_opt = MyTHREAD_OPT_STOP; - - size_t idx; - const struct timespec tomeout = {0, 0}; - - for (idx = mythread->batch_first_id; idx < (mythread->batch_first_id + mythread->batch_count); idx++) { - while(mythread->pth_list[idx].data.opt != MyTHREAD_OPT_STOP) { - mycore_thread_nanosleep(&tomeout); - } - } -} - -void mythread_stop_all(mythread_t *mythread) -{ - mythread_stream_stop_all(mythread); - mythread_batch_stop_all(mythread); -} - -void mythread_resume_all(mythread_t *mythread) -{ - if(mythread->stream_opt == MyTHREAD_OPT_UNDEF && - mythread->batch_opt == MyTHREAD_OPT_UNDEF) - return; - - if(mythread->stream_opt == MyTHREAD_OPT_WAIT || - mythread->batch_opt == MyTHREAD_OPT_WAIT) - { - mythread->stream_opt = MyTHREAD_OPT_UNDEF; - mythread->batch_opt = MyTHREAD_OPT_UNDEF; - } - else { - mythread->stream_opt = MyTHREAD_OPT_UNDEF; - mythread->batch_opt = MyTHREAD_OPT_UNDEF; - - for (size_t idx = mythread->pth_list_root; idx < mythread->pth_list_size; idx++) { - mycore_hread_mutex_post(mythread, &mythread->pth_list[idx].data); - } - } -} - -void mythread_suspend_all(mythread_t *mythread) -{ - if(mythread->stream_opt != MyTHREAD_OPT_WAIT) - mythread->stream_opt = MyTHREAD_OPT_WAIT; - - if(mythread->batch_opt != MyTHREAD_OPT_WAIT) - mythread->batch_opt = MyTHREAD_OPT_WAIT; - - const struct timespec tomeout = {0, 0}; - - for (size_t idx = mythread->pth_list_root; idx < mythread->pth_list_size; idx++) { - mycore_hread_mutex_try_wait(mythread, &mythread->pth_list[idx].data); - - while(mythread->pth_list[idx].data.opt != MyTHREAD_OPT_WAIT) { - mycore_thread_nanosleep(&tomeout); - } - } -} - -unsigned int mythread_check_status(mythread_t *mythread) -{ - for (size_t idx = mythread->pth_list_root; idx < mythread->pth_list_size; idx++) { - if(mythread->pth_list[idx].data.status) { - return mythread->pth_list[idx].data.status; - } - } - - return MyCORE_STATUS_OK; -} - -bool mythread_function_see_for_all_done(mythread_queue_list_t *queue_list, size_t thread_id) -{ - size_t done_count = 0; - - mythread_queue_list_entry_t *entry = queue_list->first; - while(entry) - { - if(entry->thread_param[ thread_id ].use >= entry->queue->nodes_uses) { - done_count++; - entry = entry->next; - } - else - break; - } - - return done_count == queue_list->count; -} - -bool mythread_function_see_opt(mythread_context_t *ctx, volatile mythread_thread_opt_t opt, size_t done_count, const struct timespec *timeout) -{ - mythread_t * mythread = ctx->mythread; - mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; - - if(done_count != queue_list->count) - return false; - - if(opt & MyTHREAD_OPT_STOP) - { - if(mythread_function_see_for_all_done(queue_list, ctx->id)) - { - ctx->opt = MyTHREAD_OPT_STOP; - mycore_hread_mutex_wait(mythread, ctx); - ctx->opt = MyTHREAD_OPT_UNDEF; - - return false; - } - } - else if(opt & MyTHREAD_OPT_QUIT) - { - if(mythread_function_see_for_all_done(queue_list, ctx->id)) - { - mycore_hread_mutex_close(mythread, ctx); - ctx->opt = MyTHREAD_OPT_QUIT; - return true; - } - } - - mycore_thread_nanosleep(timeout); - - return false; -} - -void mythread_function_queue_batch(void *arg) -{ - mythread_context_t *ctx = (mythread_context_t*)arg; - mythread_t * mythread = ctx->mythread; - mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; - - const struct timespec timeout = {0, 0}; - mycore_hread_mutex_wait(mythread, ctx); - - do { - if(mythread->batch_opt & MyTHREAD_OPT_WAIT) { - ctx->opt = MyTHREAD_OPT_WAIT; - - while (mythread->batch_opt & MyTHREAD_OPT_WAIT) { - mycore_thread_nanosleep(&timeout); - } - - ctx->opt = MyTHREAD_OPT_UNDEF; - } - - mythread_queue_list_entry_t *entry = queue_list->first; - size_t done_count = 0; - - while(entry) - { - mythread_queue_thread_param_t *thread_param = &entry->thread_param[ ctx->id ]; - - if(thread_param->use < entry->queue->nodes_uses) - { - size_t pos = thread_param->use / entry->queue->nodes_size; - size_t len = thread_param->use % entry->queue->nodes_size; - - mythread_queue_node_t *qnode = &entry->queue->nodes[pos][len]; - - //if((qnode->tree->flags & MyCORE_TREE_FLAGS_SINGLE_MODE) == 0) - ctx->func(ctx->id, (void*)qnode); - - thread_param->use += mythread->batch_count; - } - else - done_count++; - - entry = entry->next; - } - - if(done_count == queue_list->count && - mythread_function_see_opt(ctx, mythread->batch_opt, done_count, &timeout)) - break; - } - while (1); -} - -void mythread_function_queue_stream(void *arg) -{ - mythread_context_t *ctx = (mythread_context_t*)arg; - mythread_t * mythread = ctx->mythread; - mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; - - const struct timespec timeout = {0, 0}; - mycore_hread_mutex_wait(mythread, ctx); - - do { - if(mythread->stream_opt & MyTHREAD_OPT_WAIT) { - ctx->opt = MyTHREAD_OPT_WAIT; - - while (mythread->stream_opt & MyTHREAD_OPT_WAIT) { - mycore_thread_nanosleep(&timeout); - } - - ctx->opt = MyTHREAD_OPT_UNDEF; - } - - mythread_queue_list_entry_t *entry = queue_list->first; - size_t done_count = 0; - - while(entry) - { - mythread_queue_thread_param_t *thread_param = &entry->thread_param[ ctx->id ]; - - if(thread_param->use < entry->queue->nodes_uses) - { - size_t pos = thread_param->use / entry->queue->nodes_size; - size_t len = thread_param->use % entry->queue->nodes_size; - - mythread_queue_node_t *qnode = &entry->queue->nodes[pos][len]; - - //if((qnode->tree->flags & MyCORE_TREE_FLAGS_SINGLE_MODE) == 0) - ctx->func(ctx->id, (void*)qnode); - - thread_param->use++; - } - else - done_count++; - - entry = entry->next; - } - - if(done_count == queue_list->count && - mythread_function_see_opt(ctx, mythread->stream_opt, done_count, &timeout)) - break; - } - while (1); -} - -void mythread_function(void *arg) -{ - mythread_context_t *ctx = (mythread_context_t*)arg; - mythread_t * mythread = ctx->mythread; - - mycore_hread_mutex_wait(mythread, ctx); - - do { - if(mythread->stream_opt & MyTHREAD_OPT_STOP || ctx->opt & MyTHREAD_OPT_STOP) - { - ctx->opt |= MyTHREAD_OPT_DONE; - mycore_hread_mutex_wait(mythread, ctx); - - if(mythread->stream_opt & MyTHREAD_OPT_QUIT || ctx->opt & MyTHREAD_OPT_QUIT) - { - mycore_hread_mutex_close(mythread, ctx); - ctx->opt = MyTHREAD_OPT_QUIT; - break; - } - - ctx->opt = MyTHREAD_OPT_UNDEF; - } - else if(mythread->stream_opt & MyTHREAD_OPT_QUIT || ctx->opt & MyTHREAD_OPT_QUIT) - { - mycore_hread_mutex_close(mythread, ctx); - ctx->opt = MyTHREAD_OPT_QUIT; - break; - } - - ctx->func(ctx->id, ctx); - } - while (1); -} - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - - diff --git a/source/mycore/thread.h b/source/mycore/thread.h deleted file mode 100644 index 55c3d81..0000000 --- a/source/mycore/thread.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - Copyright (C) 2015-2017 Alexander Borisov - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - Author: lex.borisov@gmail.com (Alexander Borisov) -*/ - -#ifndef MyCORE_THREAD_H -#define MyCORE_THREAD_H -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "mycore/myosi.h" - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - -#if !defined(IS_OS_WINDOWS) -# include -# include -#endif - -#include -#include - -#include -#include - -#include "mycore/mystring.h" - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -#define MyTHREAD_SEM_NAME "mycore" - -/* functions */ -typedef void (*mythread_callback_before_join_f)(mythread_t* mythread); -typedef void (*mythread_process_f)(void* arg); -typedef void (*mythread_work_f)(mythread_id_t thread_id, void* arg); - -#ifdef MyCORE_BUILD_WITHOUT_THREADS - -struct mythread { - int sys_last_error; -}; - -#else /* MyCORE_BUILD_WITHOUT_THREADS */ - -void mythread_function_queue_stream(void *arg); -void mythread_function_queue_batch(void *arg); -void mythread_function(void *arg); - -// thread -struct mythread_context { - mythread_id_t id; - -#if defined(IS_OS_WINDOWS) - HANDLE mutex; -#else - pthread_mutex_t *mutex; -#endif - - size_t sem_name_size; - - mythread_work_f func; - - volatile size_t t_count; - volatile mythread_thread_opt_t opt; - - mythread_t *mythread; - unsigned int status; -}; - -struct mythread_list { -#if defined(IS_OS_WINDOWS) - HANDLE pth; -#else - pthread_t pth; -#endif - mythread_context_t data; - mythread_process_f process_func; -}; - -struct mythread_workers_list { - mythread_list_t *list; - size_t count; -}; - -struct mythread { - mythread_list_t *pth_list; - size_t pth_list_length; - size_t pth_list_size; - size_t pth_list_root; - - void *context; - - char *sem_prefix; - size_t sem_prefix_length; - -#if !defined(IS_OS_WINDOWS) - pthread_attr_t *attr; -#endif - - int sys_last_error; - - mythread_id_t batch_first_id; - mythread_id_t batch_count; - - volatile mythread_thread_opt_t stream_opt; - volatile mythread_thread_opt_t batch_opt; -}; - -mythread_id_t myhread_create_stream(mythread_t *mythread, mythread_process_f process_func, mythread_work_f func, mythread_thread_opt_t opt, mystatus_t *status); -mythread_id_t myhread_create_batch(mythread_t *mythread, mythread_process_f process_func, mythread_work_f func, mythread_thread_opt_t opt, mystatus_t *status, size_t count); - -void mycore_thread_nanosleep(const struct timespec *tomeout); - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -mythread_t * mythread_create(void); -mystatus_t mythread_init(mythread_t *mythread, const char *sem_prefix, size_t thread_count); -void mythread_clean(mythread_t *mythread); -mythread_t * mythread_destroy(mythread_t *mythread, mythread_callback_before_join_f before_join, bool self_destroy); - -void mythread_stream_quit_all(mythread_t *mythread); -void mythread_batch_quit_all(mythread_t *mythread); - -void mythread_stream_stop_all(mythread_t *mythread); -void mythread_batch_stop_all(mythread_t *mythread); - -void mythread_stop_all(mythread_t *mythread); -void mythread_queue_wait_all_for_done(mythread_t *mythread); -void mythread_resume_all(mythread_t *mythread); -void mythread_suspend_all(mythread_t *mythread); -unsigned int mythread_check_status(mythread_t *mythread); - -// queue -struct mythread_queue_node { - void* context; - void* args; - - mythread_queue_node_t* prev; -}; - -struct mythread_queue_thread_param { - volatile size_t use; -}; - -struct mythread_queue_list_entry { - mythread_queue_list_entry_t *next; - mythread_queue_list_entry_t *prev; - mythread_queue_t *queue; - mythread_queue_thread_param_t *thread_param; -}; - -struct mythread_queue_list { - mythread_queue_list_entry_t *first; - mythread_queue_list_entry_t *last; - - volatile size_t count; -}; - -struct mythread_queue { - mythread_queue_node_t **nodes; - - size_t nodes_pos; - size_t nodes_pos_size; - size_t nodes_length; - - volatile size_t nodes_uses; - volatile size_t nodes_size; - volatile size_t nodes_root; -}; - -mythread_queue_t * mythread_queue_create(size_t size, mystatus_t *status); -void mythread_queue_clean(mythread_queue_t* queue); -mythread_queue_t * mythread_queue_destroy(mythread_queue_t* token); - -void mythread_queue_node_clean(mythread_queue_node_t* qnode); - -size_t mythread_queue_count_used_node(mythread_queue_t* queue); -mythread_queue_node_t * mythread_queue_get_first_node(mythread_queue_t* queue); -mythread_queue_node_t * mythread_queue_get_prev_node(mythread_queue_node_t* qnode); -mythread_queue_node_t * mythread_queue_get_current_node(mythread_queue_t* queue); -mythread_queue_node_t * mythread_queue_node_malloc(mythread_t *mythread, mythread_queue_t* queue, mystatus_t *status); -mythread_queue_node_t * mythread_queue_node_malloc_limit(mythread_t *mythread, mythread_queue_t* queue, size_t limit, mystatus_t *status); - -#ifndef MyCORE_BUILD_WITHOUT_THREADS - -mythread_queue_list_t * mythread_queue_list_create(mystatus_t *status); -void mythread_queue_list_destroy(mythread_queue_list_t* queue_list); - -size_t mythread_queue_list_get_count(mythread_queue_list_t* queue_list); - -mythread_queue_list_entry_t * mythread_queue_list_entry_push(mythread_t *mythread, mythread_queue_t *queue, mystatus_t *status); -mythread_queue_list_entry_t * mythread_queue_list_entry_delete(mythread_t *mythread, mythread_queue_list_entry_t *entry, bool destroy_queue); -void mythread_queue_list_entry_clean(mythread_t *mythread, mythread_queue_list_entry_t *entry); -void mythread_queue_list_entry_wait_for_done(mythread_t *mythread, mythread_queue_list_entry_t *entry); - -mythread_queue_node_t * mythread_queue_node_malloc_round(mythread_t *mythread, mythread_queue_list_entry_t *entry, mystatus_t *status); - -#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* defined(__mycore__mycore_thread__) */ - diff --git a/source/mycore/thread_queue.c b/source/mycore/thread_queue.c new file mode 100644 index 0000000..133962d --- /dev/null +++ b/source/mycore/thread_queue.c @@ -0,0 +1,650 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/thread_queue.h" + +mythread_queue_t * mythread_queue_create(void) +{ + return mycore_calloc(1, sizeof(mythread_queue_t)); +} + +mystatus_t mythread_queue_init(mythread_queue_t* queue, size_t size) +{ + if(size < 32) + size = 32; + + queue->nodes_pos_size = 512; + queue->nodes_size = size; + queue->nodes = (mythread_queue_node_t**)mycore_calloc(queue->nodes_pos_size, sizeof(mythread_queue_node_t*)); + + if(queue->nodes == NULL) + return MyCORE_STATUS_THREAD_ERROR_QUEUE_NODES_MALLOC; + + queue->nodes[queue->nodes_pos] = (mythread_queue_node_t*)mycore_malloc(sizeof(mythread_queue_node_t) * queue->nodes_size); + + if(queue->nodes[queue->nodes_pos] == NULL) { + queue->nodes = mycore_free(queue->nodes); + return MyCORE_STATUS_THREAD_ERROR_QUEUE_NODE_MALLOC; + } + + return MyCORE_STATUS_OK; +} + +void mythread_queue_clean(mythread_queue_t* queue) +{ + queue->nodes_length = 0; + queue->nodes_pos = 0; + queue->nodes_root = 0; + queue->nodes_uses = 0; +} + +mythread_queue_t * mythread_queue_destroy(mythread_queue_t* queue) +{ + if(queue == NULL) + return NULL; + + if(queue->nodes) { + /* '<=' it is normal */ + for (size_t i = 0; i <= queue->nodes_pos; i++) { + mycore_free(queue->nodes[i]); + } + + mycore_free(queue->nodes); + } + + mycore_free(queue); + + return NULL; +} + +void mythread_queue_node_clean(mythread_queue_node_t* qnode) +{ + memset(qnode, 0, sizeof(mythread_queue_node_t)); +} + +mythread_queue_node_t * mythread_queue_get_prev_node(mythread_queue_node_t* qnode) +{ + return qnode->prev; +} + +mythread_queue_node_t * mythread_queue_get_current_node(mythread_queue_t* queue) +{ + return &queue->nodes[queue->nodes_pos][queue->nodes_length]; +} + +mythread_queue_node_t * mythread_queue_get_first_node(mythread_queue_t* queue) +{ + return &queue->nodes[0][0]; +} + +size_t mythread_queue_count_used_node(mythread_queue_t* queue) +{ + return queue->nodes_uses; +} + +mythread_queue_node_t * mythread_queue_node_malloc(mythread_t *mythread, mythread_queue_t* queue, mystatus_t *status) +{ + queue->nodes_length++; + + if(queue->nodes_length >= queue->nodes_size) + { + queue->nodes_pos++; + + if(queue->nodes_pos >= queue->nodes_pos_size) + { +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(mythread) + mythread_queue_list_wait_for_done(mythread, mythread->context); +#endif + size_t new_size = queue->nodes_pos_size + 512; + mythread_queue_node_t** tmp = mycore_realloc(queue->nodes, sizeof(mythread_queue_node_t*) * new_size); + + if(tmp) { + memset(&tmp[queue->nodes_pos], 0, sizeof(mythread_queue_node_t*) * (new_size - queue->nodes_pos)); + + queue->nodes = tmp; + queue->nodes_pos_size = new_size; + } + else { + if(status) + *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODES_MALLOC; + + return NULL; + } + } + + if(queue->nodes[queue->nodes_pos] == NULL) { + queue->nodes[queue->nodes_pos] = (mythread_queue_node_t*)mycore_malloc(sizeof(mythread_queue_node_t) * queue->nodes_size); + + if(queue->nodes[queue->nodes_pos] == NULL) { + if(status) + *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODE_MALLOC; + + return NULL; + } + } + + queue->nodes_length = 0; + } + + queue->nodes_uses++; + + return &queue->nodes[queue->nodes_pos][queue->nodes_length]; +} + +mythread_queue_node_t * mythread_queue_node_malloc_limit(mythread_t *mythread, mythread_queue_t* queue, size_t limit, mystatus_t *status) +{ + queue->nodes_length++; + + if(queue->nodes_uses >= limit) { + queue->nodes_uses++; + +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(mythread) + mythread_queue_list_wait_for_done(mythread, mythread->context); +#endif + queue->nodes_length = 0; + queue->nodes_pos = 0; + queue->nodes_root = 0; + queue->nodes_uses = 0; + } + else if(queue->nodes_length >= queue->nodes_size) + { + queue->nodes_pos++; + + if(queue->nodes_pos >= queue->nodes_pos_size) + { +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(mythread) + mythread_queue_list_wait_for_done(mythread, mythread->context); +#endif + size_t new_size = queue->nodes_pos_size + 512; + mythread_queue_node_t** tmp = mycore_realloc(queue->nodes, sizeof(mythread_queue_node_t*) * new_size); + + if(tmp) { + memset(&tmp[queue->nodes_pos], 0, sizeof(mythread_queue_node_t*) * (new_size - queue->nodes_pos)); + + queue->nodes = tmp; + queue->nodes_pos_size = new_size; + } + else { + if(status) + *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODES_MALLOC; + + return NULL; + } + } + + if(queue->nodes[queue->nodes_pos] == NULL) { + queue->nodes[queue->nodes_pos] = (mythread_queue_node_t*)mycore_malloc(sizeof(mythread_queue_node_t) * queue->nodes_size); + + if(queue->nodes[queue->nodes_pos] == NULL) { + if(status) + *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_NODE_MALLOC; + + return NULL; + } + } + + queue->nodes_length = 0; + } + + queue->nodes_uses++; + + return &queue->nodes[queue->nodes_pos][queue->nodes_length]; +} + +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mythread_queue_node_t * mythread_queue_node_malloc_round(mythread_t *mythread, mythread_queue_list_entry_t *entry, mystatus_t *status) +{ + mythread_queue_t* queue = entry->queue; + + queue->nodes_length++; + + if(queue->nodes_length >= queue->nodes_size) { + queue->nodes_uses++; + +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(mythread) + mythread_queue_list_entry_wait_for_done(mythread, entry); +#endif + + mythread_queue_list_entry_clean(entry); + } + else + queue->nodes_uses++; + + return &queue->nodes[queue->nodes_pos][queue->nodes_length]; +} +#endif + +#ifndef MyCORE_BUILD_WITHOUT_THREADS +/* + * Queue List + */ +mythread_queue_list_t * mythread_queue_list_create(mystatus_t *status) +{ + return (mythread_queue_list_t*)mycore_calloc(1, sizeof(mythread_queue_list_t)); +} + +void mythread_queue_list_destroy(mythread_queue_list_t* queue_list) +{ + if(queue_list == NULL) + return; + + mycore_free(queue_list); +} + +size_t mythread_queue_list_get_count(mythread_queue_list_t* queue_list) +{ + return queue_list->count; +} + +void mythread_queue_list_wait_for_done(mythread_t* mythread, mythread_queue_list_t* queue_list) +{ + if(queue_list == NULL) + return; + + mythread_queue_list_entry_t *entry = queue_list->first; + + while(entry) + { + for (size_t i = 0; i < mythread->entries_length; i++) { + while(entry->thread_param[i].use < entry->queue->nodes_uses) + mythread_nanosleep_sleep(mythread->timespec); + } + + entry = entry->next; + } +} + +bool mythread_queue_list_see_for_done(mythread_t* mythread, mythread_queue_list_t* queue_list) +{ + if(queue_list == NULL) + return true; + + mythread_queue_list_entry_t *entry = queue_list->first; + + while(entry) + { + for (size_t i = 0; i < mythread->entries_length; i++) { + if(entry->thread_param[i].use < entry->queue->nodes_uses) + return false; + } + + entry = entry->next; + } + + return true; +} + +bool mythread_queue_list_see_for_done_by_thread(mythread_t* mythread, mythread_queue_list_t* queue_list, mythread_id_t thread_id) +{ + if(queue_list == NULL) + return true; + + mythread_queue_list_entry_t *entry = queue_list->first; + + while(entry) + { + if(entry->thread_param[thread_id].use < entry->queue->nodes_uses) + return false; + + entry = entry->next; + } + + return true; +} + +/* + * Queue List Entry + */ +mythread_queue_list_entry_t * mythread_queue_list_entry_push(mythread_t** mythread_list, size_t list_size, mythread_queue_list_t* queue_list, + mythread_queue_t* queue, size_t thread_param_size, mystatus_t* status) +{ + if(status) + *status = MyCORE_STATUS_OK; + + /* create new entry */ + mythread_queue_list_entry_t* entry = (mythread_queue_list_entry_t*)mycore_calloc(1, sizeof(mythread_queue_list_entry_t)); + if(entry == NULL) { + if(status) + *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_MALLOC; + + return NULL; + } + + /* create thread params */ + entry->thread_param_size = thread_param_size; + + if(thread_param_size) { + entry->thread_param = (mythread_queue_thread_param_t*)mycore_calloc(thread_param_size, sizeof(mythread_queue_thread_param_t)); + + if(entry->thread_param == NULL) { + mycore_free(entry); + + if(status) + *status = MyCORE_STATUS_THREAD_ERROR_QUEUE_MALLOC; + + return NULL; + } + } + else + entry->thread_param = NULL; + + entry->queue = queue; + + for(size_t i = 0; i < list_size; i++) { + if(mythread_list[i]->type == MyTHREAD_TYPE_BATCH) { + mythread_queue_list_entry_make_batch(mythread_list[i], entry, mythread_list[i]->id_increase, mythread_list[i]->entries_length); + } + + if(mythread_list[i]) + mythread_suspend(mythread_list[i]); + } + + if(queue_list->first) { + queue_list->last->next = entry; + entry->prev = queue_list->last; + + queue_list->last = entry; + } + else { + queue_list->first = entry; + queue_list->last = entry; + } + + queue_list->count++; + + for(size_t i = 0; i < list_size; i++) + if(mythread_list[i]) + mythread_resume(mythread_list[i]); + + return entry; +} + +mythread_queue_list_entry_t * mythread_queue_list_entry_delete(mythread_t** mythread_list, size_t list_size, mythread_queue_list_t *queue_list, mythread_queue_list_entry_t *entry, bool destroy_queue) +{ + for(size_t i = 0; i < list_size; i++) + if(mythread_list[i]) + mythread_suspend(mythread_list[i]); + + mythread_queue_list_entry_t *next = entry->next; + mythread_queue_list_entry_t *prev = entry->prev; + + if(prev) + prev->next = next; + + if(next) + next->prev = prev; + + if(queue_list->first == entry) + queue_list->first = next; + + if(queue_list->last == entry) + queue_list->last = prev; + + queue_list->count--; + + for(size_t i = 0; i < list_size; i++) + if(mythread_list[i]) + mythread_resume(mythread_list[i]); + + if(destroy_queue && entry->queue) + mythread_queue_destroy(entry->queue); + + if(entry->thread_param) + mycore_free(entry->thread_param); + + mycore_free(entry); + + return NULL; +} + +void mythread_queue_list_entry_clean(mythread_queue_list_entry_t *entry) +{ + if(entry == NULL) + return; + + mythread_queue_clean(entry->queue); + + for (size_t i = 0; i < entry->thread_param_size; i++) { + memset(&entry->thread_param[i], 0, sizeof(mythread_queue_thread_param_t)); + } +} + +void mythread_queue_list_entry_wait_for_done(mythread_t* mythread, mythread_queue_list_entry_t *entry) +{ + if(entry == NULL) + return; + + for(size_t i = 0; i < entry->thread_param_size; i++) { + while(entry->thread_param[i].use < entry->queue->nodes_uses) + mythread_nanosleep_sleep(mythread->timespec); + } +} + +bool mythread_queue_list_entry_see_for_done(mythread_queue_list_entry_t *entry) +{ + if(entry == NULL) + return true; + + for(size_t i = 0; i < entry->thread_param_size; i++) { + if(entry->thread_param[i].use < entry->queue->nodes_uses) + return false; + } + + return true; +} + +void mythread_queue_list_entry_make_batch(mythread_t* mythread, mythread_queue_list_entry_t* entry, size_t from, size_t count) +{ + size_t i = 0; + while(from <= count) { + entry->thread_param[from].use = i; + i++; from++; + } +} + +/* + * Thread Process Functions + */ +bool mythread_function_see_opt(mythread_context_t *ctx, volatile mythread_thread_opt_t opt, mythread_id_t thread_id, size_t done_count, void* timeout) +{ + mythread_t *mythread = ctx->mythread; + mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; + + if(done_count != queue_list->count) + return false; + + if(opt & MyTHREAD_OPT_STOP) + { + if(mythread_queue_list_see_for_done_by_thread(mythread, queue_list, thread_id)) + { + ctx->opt = MyTHREAD_OPT_STOP; + mythread_mutex_wait(mythread, ctx->mutex); + ctx->opt = MyTHREAD_OPT_UNDEF; + + return false; + } + } + else if(opt & MyTHREAD_OPT_QUIT) + { + if(mythread_queue_list_see_for_done_by_thread(mythread, queue_list, thread_id)) + { + mythread_mutex_close(mythread, ctx->mutex); + mythread_nanosleep_destroy(ctx->timespec); + + ctx->opt = MyTHREAD_OPT_QUIT; + return true; + } + } + + mythread_nanosleep_sleep(timeout); + + return false; +} + +void mythread_function_queue_batch(void *arg) +{ + mythread_context_t *ctx = (mythread_context_t*)arg; + mythread_t *mythread = ctx->mythread; + mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; + mythread_id_t thread_id = myhread_increase_id_by_entry_id(mythread, ctx->id); + + mythread_mutex_wait(mythread, ctx->mutex); + + do { + if(mythread->opt & MyTHREAD_OPT_WAIT) { + ctx->opt = MyTHREAD_OPT_WAIT; + + while (mythread->opt & MyTHREAD_OPT_WAIT) + mythread_nanosleep_sleep(ctx->timespec); + + ctx->opt = MyTHREAD_OPT_UNDEF; + } + + mythread_queue_list_entry_t *entry = queue_list->first; + size_t done_count = 0; + + while(entry) + { + mythread_queue_thread_param_t *thread_param = &entry->thread_param[ thread_id ]; + + if(thread_param->use < entry->queue->nodes_uses) + { + size_t pos = thread_param->use / entry->queue->nodes_size; + size_t len = thread_param->use % entry->queue->nodes_size; + + mythread_queue_node_t *qnode = &entry->queue->nodes[pos][len]; + + //if((qnode->tree->flags & MyCORE_TREE_FLAGS_SINGLE_MODE) == 0) + ctx->func(ctx->id, (void*)qnode); + + thread_param->use += mythread->entries_length; + } + else + done_count++; + + entry = entry->next; + } + + if(done_count == queue_list->count && + mythread_function_see_opt(ctx, mythread->opt, thread_id, done_count, ctx->timespec)) + { + break; + } + } + while (1); +} + +void mythread_function_queue_stream(void *arg) +{ + mythread_context_t *ctx = (mythread_context_t*)arg; + mythread_t * mythread = ctx->mythread; + mythread_queue_list_t *queue_list = (mythread_queue_list_t*)mythread->context; + mythread_id_t thread_id = myhread_increase_id_by_entry_id(mythread, ctx->id); + + mythread_mutex_wait(mythread, ctx->mutex); + + do { + if(mythread->opt & MyTHREAD_OPT_WAIT) { + ctx->opt = MyTHREAD_OPT_WAIT; + + while (mythread->opt & MyTHREAD_OPT_WAIT) { + mythread_nanosleep_sleep(ctx->timespec); + } + + ctx->opt = MyTHREAD_OPT_UNDEF; + } + + mythread_queue_list_entry_t *entry = queue_list->first; + size_t done_count = 0; + + while(entry) + { + mythread_queue_thread_param_t *thread_param = &entry->thread_param[ thread_id ]; + + if(thread_param->use < entry->queue->nodes_uses) + { + size_t pos = thread_param->use / entry->queue->nodes_size; + size_t len = thread_param->use % entry->queue->nodes_size; + + mythread_queue_node_t *qnode = &entry->queue->nodes[pos][len]; + + //if((qnode->tree->flags & MyCORE_TREE_FLAGS_SINGLE_MODE) == 0) + ctx->func(ctx->id, (void*)qnode); + + thread_param->use++; + } + else + done_count++; + + entry = entry->next; + } + + if(done_count == queue_list->count && + mythread_function_see_opt(ctx, mythread->opt, thread_id, done_count, ctx->timespec)) + { + break; + } + } + while(1); +} + +void mythread_function(void *arg) +{ + mythread_context_t *ctx = (mythread_context_t*)arg; + mythread_t * mythread = ctx->mythread; + + mythread_mutex_wait(mythread, ctx->mutex); + + do { + if(mythread->opt & MyTHREAD_OPT_STOP || ctx->opt & MyTHREAD_OPT_STOP) + { + ctx->opt |= MyTHREAD_OPT_DONE; + mythread_mutex_wait(mythread, ctx->mutex); + + if(mythread->opt & MyTHREAD_OPT_QUIT || ctx->opt & MyTHREAD_OPT_QUIT) + { + mythread_mutex_close(mythread, ctx->mutex); + mythread_nanosleep_destroy(ctx->timespec); + + ctx->opt = MyTHREAD_OPT_QUIT; + break; + } + + ctx->opt = MyTHREAD_OPT_UNDEF; + } + else if(mythread->opt & MyTHREAD_OPT_QUIT || ctx->opt & MyTHREAD_OPT_QUIT) + { + mythread_mutex_close(mythread, ctx->mutex); + mythread_nanosleep_destroy(ctx->timespec); + + ctx->opt = MyTHREAD_OPT_QUIT; + break; + } + + ctx->func(ctx->id, ctx); + } + while(1); +} + +#endif diff --git a/source/mycore/thread_queue.h b/source/mycore/thread_queue.h new file mode 100644 index 0000000..7311714 --- /dev/null +++ b/source/mycore/thread_queue.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#ifndef MyCORE_THREAD_QUEUE_H +#define MyCORE_THREAD_QUEUE_H +#pragma once + +#include "mycore/myosi.h" +#include "mycore/mythread.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +// queue +struct mythread_queue_node { + void* context; + void* args; + + mythread_queue_node_t* prev; +}; + +struct mythread_queue_thread_param { + volatile size_t use; +}; + +struct mythread_queue_list_entry { + mythread_queue_t* queue; + mythread_queue_thread_param_t* thread_param; + size_t thread_param_size; + + mythread_queue_list_entry_t* next; + mythread_queue_list_entry_t* prev; +}; + +struct mythread_queue_list { + mythread_queue_list_entry_t *first; + mythread_queue_list_entry_t *last; + + volatile size_t count; +}; + +struct mythread_queue { + mythread_queue_node_t **nodes; + + size_t nodes_pos; + size_t nodes_pos_size; + size_t nodes_length; + + volatile size_t nodes_uses; + volatile size_t nodes_size; + volatile size_t nodes_root; +}; + +mythread_queue_t * mythread_queue_create(void); +mystatus_t mythread_queue_init(mythread_queue_t* queue, size_t size); +void mythread_queue_clean(mythread_queue_t* queue); +mythread_queue_t * mythread_queue_destroy(mythread_queue_t* token); + +void mythread_queue_node_clean(mythread_queue_node_t* qnode); +size_t mythread_queue_count_used_node(mythread_queue_t* queue); + +mythread_queue_node_t * mythread_queue_get_first_node(mythread_queue_t* queue); +mythread_queue_node_t * mythread_queue_get_prev_node(mythread_queue_node_t* qnode); +mythread_queue_node_t * mythread_queue_get_current_node(mythread_queue_t* queue); + +mythread_queue_node_t * mythread_queue_node_malloc(mythread_t *mythread, mythread_queue_t* queue, mystatus_t *status); +mythread_queue_node_t * mythread_queue_node_malloc_limit(mythread_t *mythread, mythread_queue_t* queue, size_t limit, mystatus_t *status); +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mythread_queue_node_t * mythread_queue_node_malloc_round(mythread_t *mythread, mythread_queue_list_entry_t *entry, mystatus_t *status); +#endif + +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mythread_queue_list_t * mythread_queue_list_create(mystatus_t *status); +void mythread_queue_list_destroy(mythread_queue_list_t* queue_list); +size_t mythread_queue_list_get_count(mythread_queue_list_t* queue_list); + +void mythread_queue_list_wait_for_done(mythread_t* mythread, mythread_queue_list_t* queue_list); +bool mythread_queue_list_see_for_done(mythread_t* mythread, mythread_queue_list_t* queue_list); +bool mythread_queue_list_see_for_done_by_thread(mythread_t* mythread, mythread_queue_list_t* queue_list, mythread_id_t thread_id); + +mythread_queue_list_entry_t * mythread_queue_list_entry_push(mythread_t** mythread_list, size_t list_size, mythread_queue_list_t* queue_list, mythread_queue_t* queue, size_t thread_param_size, mystatus_t* status); +mythread_queue_list_entry_t * mythread_queue_list_entry_delete(mythread_t** mythread_list, size_t list_size, mythread_queue_list_t *queue_list, mythread_queue_list_entry_t *entry, bool destroy_queue); +void mythread_queue_list_entry_clean(mythread_queue_list_entry_t *entry); +void mythread_queue_list_entry_wait_for_done(mythread_t *mythread, mythread_queue_list_entry_t *entry); +void mythread_queue_list_entry_make_batch(mythread_t* mythread, mythread_queue_list_entry_t* entry, size_t from, size_t length); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* MyCORE_THREAD_QUEUE_H */ diff --git a/source/mycore/utils/mchar_async.c b/source/mycore/utils/mchar_async.c index 14fe1ad..23bd322 100644 --- a/source/mycore/utils/mchar_async.c +++ b/source/mycore/utils/mchar_async.c @@ -20,16 +20,12 @@ #include "mycore/utils/mchar_async.h" -mchar_async_t * mchar_async_create(size_t pos_size, size_t size) +mchar_async_t * mchar_async_create(void) { - mchar_async_t *mcobj_async = (mchar_async_t*)mycore_calloc(1, sizeof(mchar_async_t)); - - mchar_async_init(mcobj_async, pos_size, size); - - return mcobj_async; + return (mchar_async_t*)mycore_calloc(1, sizeof(mchar_async_t)); } -void mchar_async_init(mchar_async_t *mchar_async, size_t chunk_len, size_t char_size) +mystatus_t mchar_async_init(mchar_async_t *mchar_async, size_t chunk_len, size_t char_size) { if(char_size < 4096) char_size = 4096; @@ -38,25 +34,58 @@ void mchar_async_init(mchar_async_t *mchar_async, size_t chunk_len, size_t char_ mchar_async->chunks_size = chunk_len; mchar_async->chunks_pos_size = 1024; + + /* Chunck, list of mchar_async_chunk_t* */ mchar_async->chunks = (mchar_async_chunk_t**)mycore_calloc(mchar_async->chunks_pos_size, sizeof(mchar_async_chunk_t*)); + + if(mchar_async->chunks == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + /* Init first mchar_async_chunk_t* */ mchar_async->chunks[0] = (mchar_async_chunk_t*)mycore_calloc(mchar_async->chunks_size, sizeof(mchar_async_chunk_t)); - mchar_async_cache_init(&mchar_async->chunk_cache); + if(mchar_async->chunks[0] == NULL) { + mchar_async->chunks = mycore_free(mchar_async->chunks); + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + } + + /* Init cache */ + mystatus_t status = mchar_async_cache_init(&mchar_async->chunk_cache); + + if(status) { + mycore_free(mchar_async->chunks[0]); + mchar_async->chunks = mycore_free(mchar_async->chunks); + + return status; + } mchar_async->nodes_length = 0; mchar_async->nodes_size = 64; mchar_async->nodes = (mchar_async_node_t*)mycore_calloc(mchar_async->nodes_size, sizeof(mchar_async_node_t)); + if(mchar_async->nodes == NULL) + return status; + mchar_async->nodes_cache_length = 0; mchar_async->nodes_cache_size = mchar_async->nodes_size; mchar_async->nodes_cache = (size_t*)mycore_malloc(mchar_async->nodes_cache_size * sizeof(size_t)); + if(mchar_async->nodes_cache == NULL) + return status; + mchar_async_clean(mchar_async); mchar_async->mcsync = mcsync_create(); + if(mchar_async->mcsync == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + if((status = mcsync_init(mchar_async->mcsync))) + return status; + + return MyCORE_STATUS_OK; } -void mchar_async_clean(mchar_async_t *mchar_async) +mystatus_t mchar_async_clean(mchar_async_t *mchar_async) { mchar_async->chunks_length = 0; mchar_async->chunks_pos_length = 1; @@ -69,8 +98,14 @@ void mchar_async_clean(mchar_async_t *mchar_async) mchar_async_cache_clean(&node->cache); node->chunk = mchar_async_chunk_malloc(mchar_async, node, mchar_async->origin_size); + + if(node->chunk == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + node->chunk->prev = 0; } + + return MyCORE_STATUS_OK; } mchar_async_t * mchar_async_destroy(mchar_async_t *mchar_async, int destroy_self) @@ -159,6 +194,8 @@ mchar_async_chunk_t * mchar_async_chunk_malloc_without_lock(mchar_async_t *mchar if(index) return (mchar_async_chunk_t*)mchar_async->chunk_cache.nodes[index].value; + else + return NULL; } if(mchar_async->chunks_length >= mchar_async->chunks_size) @@ -178,6 +215,8 @@ mchar_async_chunk_t * mchar_async_chunk_malloc_without_lock(mchar_async_t *mchar mchar_async->chunks = tmp_pos; } + else + return NULL; } if(mchar_async->chunks[current_idx] == NULL) { @@ -185,6 +224,8 @@ mchar_async_chunk_t * mchar_async_chunk_malloc_without_lock(mchar_async_t *mchar if(tmp) mchar_async->chunks[current_idx] = tmp; + else + return NULL; } mchar_async->chunks_length = 0; @@ -195,6 +236,9 @@ mchar_async_chunk_t * mchar_async_chunk_malloc_without_lock(mchar_async_t *mchar mchar_async_mem_malloc(mchar_async, node, chunk, length); + if(chunk->begin == NULL) + return NULL; + return chunk; } @@ -207,9 +251,14 @@ mchar_async_chunk_t * mchar_async_chunk_malloc(mchar_async_t *mchar_async, mchar return chunk; } -size_t mchar_async_node_add(mchar_async_t *mchar_async) +size_t mchar_async_node_add(mchar_async_t *mchar_async, mystatus_t* status) { - mcsync_lock(mchar_async->mcsync); + if(mcsync_lock(mchar_async->mcsync)) { + if(status) + *status = MyCORE_STATUS_ASYNC_ERROR_LOCK; + + return 0; + } size_t node_idx; @@ -220,6 +269,9 @@ size_t mchar_async_node_add(mchar_async_t *mchar_async) } else { if(mchar_async->nodes_length >= mchar_async->nodes_size) { + if(status) + *status = MyCORE_STATUS_ERROR_NO_FREE_SLOT; + mcsync_unlock(mchar_async->mcsync); return 0; } @@ -230,15 +282,32 @@ size_t mchar_async_node_add(mchar_async_t *mchar_async) mchar_async_node_t *node = &mchar_async->nodes[node_idx]; - mchar_async_cache_init(&node->cache); + if(mchar_async_cache_init(&node->cache)) { + if(status) + *status = MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + mcsync_unlock(mchar_async->mcsync); + return 0; + } node->chunk = mchar_async_chunk_malloc_without_lock(mchar_async, node, mchar_async->origin_size); + if(node->chunk == NULL) { + if(status) + *status = MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + mcsync_unlock(mchar_async->mcsync); + return 0; + } + node->chunk->next = NULL; node->chunk->prev = NULL; mcsync_unlock(mchar_async->mcsync); + if(status) + *status = MyCORE_STATUS_OK; + return node_idx; } @@ -486,7 +555,7 @@ void mchar_async_free(mchar_async_t *mchar_async, size_t node_idx, char *entry) mchar_async_cache_add(&mchar_async->nodes[node_idx].cache, entry, *(size_t*)(entry - sizeof(size_t))); } -void mchar_async_cache_init(mchar_async_cache_t *cache) +mystatus_t mchar_async_cache_init(mchar_async_cache_t *cache) { cache->count = 0; cache->nodes_root = 0; @@ -494,6 +563,9 @@ void mchar_async_cache_init(mchar_async_cache_t *cache) cache->nodes_size = 1024; cache->nodes = (mchar_async_cache_node_t*)mycore_malloc(sizeof(mchar_async_cache_node_t) * cache->nodes_size); + if(cache->nodes == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + cache->nodes[0].left = 0; cache->nodes[0].right = 0; cache->nodes[0].size = 0; @@ -502,6 +574,13 @@ void mchar_async_cache_init(mchar_async_cache_t *cache) cache->index_length = 0; cache->index_size = cache->nodes_size; cache->index = (size_t*)mycore_malloc(sizeof(size_t) * cache->index_size); + + if(cache->index == NULL) { + cache->nodes = mycore_free(cache->nodes); + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + } + + return MyCORE_STATUS_OK; } void mchar_async_cache_clean(mchar_async_cache_t *cache) @@ -664,6 +743,8 @@ size_t mchar_async_cache_delete(mchar_async_cache_t *cache, size_t size) cache->index = tmp; cache->index_size = new_size; } + else + return 0; } cache->count--; diff --git a/source/mycore/utils/mchar_async.h b/source/mycore/utils/mchar_async.h index 2b5358e..f7fe54b 100644 --- a/source/mycore/utils/mchar_async.h +++ b/source/mycore/utils/mchar_async.h @@ -96,16 +96,16 @@ struct mchar_async { typedef mchar_async_t; -mchar_async_t * mchar_async_create(size_t pos_size, size_t size); -void mchar_async_init(mchar_async_t *mchar_async, size_t chunk_len, size_t char_size); -void mchar_async_clean(mchar_async_t *mchar_async); +mchar_async_t * mchar_async_create(void); +mystatus_t mchar_async_init(mchar_async_t *mchar_async, size_t chunk_len, size_t char_size); +mystatus_t mchar_async_clean(mchar_async_t *mchar_async); mchar_async_t * mchar_async_destroy(mchar_async_t *mchar_async, int destroy_self); char * mchar_async_malloc(mchar_async_t *mchar_async, size_t node_idx, size_t size); char * mchar_async_realloc(mchar_async_t *mchar_async, size_t node_idx, char *data, size_t data_len, size_t new_size); void mchar_async_free(mchar_async_t *mchar_async, size_t node_idx, char *entry); -size_t mchar_async_node_add(mchar_async_t *mchar_async); +size_t mchar_async_node_add(mchar_async_t *mchar_async, mystatus_t* status); void mchar_async_node_clean(mchar_async_t *mchar_async, size_t node_idx); void mchar_async_node_delete(mchar_async_t *mchar_async, size_t node_idx); @@ -116,7 +116,7 @@ char * mchar_async_crop_first_chars_without_cache(char *data, size_t crop_len); size_t mchar_async_get_size_by_data(const char *data); // cache -void mchar_async_cache_init(mchar_async_cache_t *cache); +mystatus_t mchar_async_cache_init(mchar_async_cache_t *cache); mchar_async_cache_t * mchar_async_cache_destroy(mchar_async_cache_t *cache, bool self_destroy); void mchar_async_cache_clean(mchar_async_cache_t *cache); diff --git a/source/mycore/utils/mcobject_async.c b/source/mycore/utils/mcobject_async.c index 40e7679..398f0dd 100644 --- a/source/mycore/utils/mcobject_async.c +++ b/source/mycore/utils/mcobject_async.c @@ -78,6 +78,11 @@ mcobject_async_status_t mcobject_async_init(mcobject_async_t *mcobj_async, size_ mcobject_async_clean(mcobj_async); mcobj_async->mcsync = mcsync_create(); + if(mcobj_async->mcsync == NULL) + return MCOBJECT_ASYNC_STATUS_ERROR_MEMORY_ALLOCATION; + + if(mcsync_init(mcobj_async->mcsync)) + return MCOBJECT_ASYNC_STATUS_ERROR_MEMORY_ALLOCATION; return MCOBJECT_ASYNC_STATUS_OK; } @@ -251,7 +256,9 @@ mcobject_async_chunk_t * mcobject_async_chunk_malloc_without_lock(mcobject_async mcobject_async_chunk_t * mcobject_async_chunk_malloc(mcobject_async_t *mcobj_async, size_t length, mcobject_async_status_t *status) { - mcsync_lock(mcobj_async->mcsync); + if(mcsync_lock(mcobj_async->mcsync)) + return NULL; + mcobject_async_chunk_t* chunk = mcobject_async_chunk_malloc_without_lock(mcobj_async, length, status); mcsync_unlock(mcobj_async->mcsync); diff --git a/source/mycore/utils/mcsync.c b/source/mycore/utils/mcsync.c index 5871160..bbaef9f 100644 --- a/source/mycore/utils/mcsync.c +++ b/source/mycore/utils/mcsync.c @@ -20,109 +20,80 @@ #include "mycore/utils/mcsync.h" -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) && ((defined(__GNUC__) && __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || \ - defined(__ATOMIC_SEQ_CST)) -#define MyCORE_FORCE_SPINLOCK -#endif - -#if defined(MyCORE_FORCE_SPINLOCK) -static int mcsync_atomic_compare_exchange(int* ptr, int compare, int exchange) -{ - return __atomic_compare_exchange_n(ptr, &compare, exchange, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); -} - -static void mcsync_atomic_store(int* ptr, int value) -{ - __atomic_store_n(ptr, 0, __ATOMIC_SEQ_CST); -} -#endif - mcsync_t * mcsync_create(void) { - return calloc(1, sizeof(mcsync_t)); + return mycore_calloc(1, sizeof(mcsync_t)); } + + mcsync_status_t mcsync_init(mcsync_t* mcsync) { - mcsync_clean(mcsync); - return MCSYNC_STATUS_OK; -} - -mcsync_t * mcsync_destroy(mcsync_t* mcsync, int destroy_self) -{ - if(mcsync == NULL) - return NULL; +#ifndef MyCORE_BUILD_WITHOUT_THREADS + /* spinlock */ + if((mcsync->spinlock = mcsync_spin_create()) == NULL) + return MCSYNC_STATUS_NOT_OK; -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) && !defined(MyCORE_FORCE_SPINLOCK) - if(mcsync->mutex) { - pthread_mutex_destroy(mcsync->mutex); - mycore_free(mcsync->mutex); + mcsync_status_t status = mcsync_spin_init(mcsync->spinlock); + if(status) { + mcsync_spin_destroy(mcsync->spinlock); + return status; + } + + /* mutex */ + if((mcsync->mutex = mcsync_mutex_create()) == NULL) + return MCSYNC_STATUS_NOT_OK; + + if((status = mcsync_mutex_init(mcsync->mutex))) { + mcsync_spin_destroy(mcsync->spinlock); + mcsync_mutex_destroy(mcsync->mutex); + + return status; } #endif - if(destroy_self) - mycore_free(mcsync); - - return NULL; + return MCSYNC_STATUS_OK; } void mcsync_clean(mcsync_t* mcsync) { - mcsync->spinlock = 0; +#ifndef MyCORE_BUILD_WITHOUT_THREADS + mcsync_spin_clean(mcsync->spinlock); + mcsync_mutex_clean(mcsync->mutex); +#endif +} + +mcsync_t * mcsync_destroy(mcsync_t* mcsync, int destroy_self) +{ +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(mcsync == NULL) + return NULL; + + mcsync_spin_destroy(mcsync->spinlock); + mcsync_mutex_destroy(mcsync->mutex); +#endif + if(destroy_self) { + mycore_free(mcsync); + return NULL; + } + + return mcsync; } mcsync_status_t mcsync_lock(mcsync_t* mcsync) { -#if defined(MyCORE_FORCE_SPINLOCK) - while (!mcsync_atomic_compare_exchange(&mcsync->spinlock, 0, 1)) {} -#elif !defined(MyCORE_BUILD_WITHOUT_THREADS) - mcsync_mutex_lock(mcsync); +#ifndef MyCORE_BUILD_WITHOUT_THREADS + return mcsync_spin_lock(mcsync->spinlock); +#else + return MyCORE_STATUS_OK; #endif - - return MCSYNC_STATUS_OK; } mcsync_status_t mcsync_unlock(mcsync_t* mcsync) { -#if defined(MyCORE_FORCE_SPINLOCK) - mcsync_atomic_store(&mcsync->spinlock, 0); -#elif !defined(MyCORE_BUILD_WITHOUT_THREADS) - mcsync_mutex_unlock(mcsync); -#endif - - return MCSYNC_STATUS_OK; -} - -mcsync_status_t mcsync_mutex_lock(mcsync_t* mcsync) -{ -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) && !defined(MyCORE_FORCE_SPINLOCK) - if(mcsync->mutex == NULL) { - mcsync->mutex = (pthread_mutex_t*)mycore_malloc(sizeof(pthread_mutex_t)); - - if(mcsync->mutex == NULL) - return MCSYNC_STATUS_ERROR_MEM_ALLOCATE; - - pthread_mutex_init(mcsync->mutex, NULL); - } - - if(pthread_mutex_lock(mcsync->mutex) == 0) - return MCSYNC_STATUS_OK; - else - return MCSYNC_STATUS_NOT_OK; +#ifndef MyCORE_BUILD_WITHOUT_THREADS + return mcsync_spin_unlock(mcsync->spinlock); #else - return MCSYNC_STATUS_NOT_OK; + return MyCORE_STATUS_OK; #endif } - -mcsync_status_t mcsync_mutex_unlock(mcsync_t* mcsync) -{ -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) && !defined(MyCORE_FORCE_SPINLOCK) - if(pthread_mutex_unlock(mcsync->mutex) == 0) - return MCSYNC_STATUS_OK; - else - return MCSYNC_STATUS_NOT_OK; -#else - return MCSYNC_STATUS_NOT_OK; -#endif -} - diff --git a/source/mycore/utils/mcsync.h b/source/mycore/utils/mcsync.h index 30042a9..80fa896 100644 --- a/source/mycore/utils/mcsync.h +++ b/source/mycore/utils/mcsync.h @@ -22,37 +22,22 @@ #define MyCORE_UTILS_MCSYNC_H #pragma once +#include "mycore/myosi.h" + #ifdef __cplusplus extern "C" { #endif - -#include -#include -#include - -#include "mycore/myosi.h" - -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) -#if defined(IS_OS_WINDOWS) - typedef CRITICAL_SECTION pthread_mutex_t; - typedef unsigned long pthread_mutexattr_t; -#else -# include -#endif -#endif enum mcsync_status { - MCSYNC_STATUS_OK = 0, - MCSYNC_STATUS_NOT_OK = 1, - MCSYNC_STATUS_ERROR_MEM_ALLOCATE = 2 + MCSYNC_STATUS_OK = 0x00, + MCSYNC_STATUS_NOT_OK = 0x01, + MCSYNC_STATUS_ERROR_MEM_ALLOCATE = 0x02 } typedef mcsync_status_t; struct mcsync { - int spinlock; -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) - pthread_mutex_t *mutex; -#endif + int* spinlock; + void* mutex; } typedef mcsync_t; @@ -61,37 +46,26 @@ mcsync_status_t mcsync_init(mcsync_t* mcsync); void mcsync_clean(mcsync_t* mcsync); mcsync_t * mcsync_destroy(mcsync_t* mcsync, int destroy_self); -mcsync_status_t mcsync_lock(mcsync_t* mclock); -mcsync_status_t mcsync_unlock(mcsync_t* mclock); +mcsync_status_t mcsync_lock(mcsync_t* mcsync); +mcsync_status_t mcsync_unlock(mcsync_t* mcsync); -mcsync_status_t mcsync_mutex_lock(mcsync_t* mclock); -mcsync_status_t mcsync_mutex_unlock(mcsync_t* mclock); +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mcsync_status_t mcsync_spin_lock(void* spinlock); +mcsync_status_t mcsync_spin_unlock(void* spinlock); -#if !defined(MyCORE_BUILD_WITHOUT_THREADS) && defined(IS_OS_WINDOWS) -static __inline int pthread_mutex_lock(pthread_mutex_t *mutex) -{ - EnterCriticalSection(mutex); - return 0; -} +mcsync_status_t mcsync_mutex_lock(void* mutex); +mcsync_status_t mcsync_mutex_try_lock(void* mutex); +mcsync_status_t mcsync_mutex_unlock(void* mutex); -static __inline int pthread_mutex_unlock(pthread_mutex_t *mutex) -{ - LeaveCriticalSection(mutex); - return 0; -} +void * mcsync_spin_create(void); +mcsync_status_t mcsync_spin_init(void* spinlock); +void mcsync_spin_clean(void* spinlock); +void mcsync_spin_destroy(void* spinlock); -static __inline int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *a) -{ - (void)a; - InitializeCriticalSection(mutex); - return 0; -} - -static __inline int pthread_mutex_destroy(pthread_mutex_t *mutex) -{ - DeleteCriticalSection(mutex); - return 0; -} +void * mcsync_mutex_create(void); +mcsync_status_t mcsync_mutex_init(void* mutex); +void mcsync_mutex_clean(void* mutex); +void mcsync_mutex_destroy(void* mutex); #endif #ifdef __cplusplus diff --git a/source/mycore/utils/mctree.c b/source/mycore/utils/mctree.c index 6b68404..6d5e281 100644 --- a/source/mycore/utils/mctree.c +++ b/source/mycore/utils/mctree.c @@ -25,10 +25,18 @@ mctree_t * mctree_create(size_t start_size) { mctree_t* mctree = (mctree_t*)mycore_malloc(sizeof(mctree_t)); + if(mctree == NULL) + return NULL; + mctree->nodes_size = start_size + 512; mctree->nodes_length = start_size + 1; mctree->nodes = (mctree_node_t*)mycore_calloc(mctree->nodes_size, sizeof(mctree_node_t)); + if(mctree->nodes == NULL) { + mycore_free(mctree); + return NULL; + } + mctree->start_size = start_size; return mctree; diff --git a/source/mycore/utils/mhash.c b/source/mycore/utils/mhash.c index a3e7384..59c57af 100644 --- a/source/mycore/utils/mhash.c +++ b/source/mycore/utils/mhash.c @@ -45,11 +45,19 @@ mycore_utils_mhash_t * mycore_utils_mhash_create(void) mystatus_t mycore_utils_mhash_init(mycore_utils_mhash_t* mhash, size_t table_size, size_t max_depth) { - mhash->mchar_obj = mchar_async_create(128, 4096); + mystatus_t status; + + mhash->mchar_obj = mchar_async_create(); if(mhash->mchar_obj == NULL) return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; - mhash->mchar_node = mchar_async_node_add(mhash->mchar_obj); + if((status = mchar_async_init(mhash->mchar_obj, 128, 4096))) + return status; + + /* nodest data for input char* */ + mhash->mchar_node = mchar_async_node_add(mhash->mchar_obj, &status); + if(status) + return status; if(table_size < 128) table_size = 128; diff --git a/source/mycss/Makefile.mk b/source/mycss/Makefile.mk index 3303402..14e8478 100644 --- a/source/mycss/Makefile.mk +++ b/source/mycss/Makefile.mk @@ -1,12 +1,10 @@ -find_files_h = $(wildcard $(SRCDIR)/mycss/$(dir)/*.h) -find_files_c = $(wildcard $(SRCDIR)/mycss/$(dir)/*.c) +mycss_dirs := . selectors namespace media values property declaration +mycss_objs := $(call MODEST_UTILS_OBJS,mycss,$(mycss_dirs)) -SUBDIRS := . selectors namespace media values property declaration -HDRS += $(foreach dir,$(SUBDIRS),$(find_files_h)) -SRCS += $(foreach dir,$(SUBDIRS),$(find_files_c)) +mycss_all: $(mycss_objs) -mycss_clone: MyCSS_DIR_$(SUBDIRS) +mycss_clean: + rm -f $(mycss_objs) -MyCSS_DIR_$(SUBDIRS): - mkdir -p $(INCLUDE_TMP)/mycss/$(patsubst MyCSS_DIR_%,%,$@) - cp $(SRCDIR)/mycss/$(patsubst MyCSS_DIR_%,%,$@)/*.h $(INCLUDE_TMP)/mycss/$(patsubst MyCSS_DIR_%,%,$@)/ +mycss_clone: + $(call MODEST_UTILS_HDRS_CLONE,mycss,$(mycss_dirs)) diff --git a/source/mycss/entry.c b/source/mycss/entry.c index b56d2eb..d3876be 100644 --- a/source/mycss/entry.c +++ b/source/mycss/entry.c @@ -28,6 +28,8 @@ mycss_entry_t * mycss_entry_create(void) mystatus_t mycss_entry_init(mycss_t* mycss, mycss_entry_t* entry) { + mystatus_t status; + entry->mycss = mycss; entry->parser = NULL; entry->parser_switch = NULL; @@ -35,9 +37,21 @@ mystatus_t mycss_entry_init(mycss_t* mycss, mycss_entry_t* entry) entry->parser_ending_token = MyCSS_TOKEN_TYPE_UNDEF; // Other init - entry->mchar = mchar_async_create(128, (4096 * 5)); - entry->mchar_node_id = mchar_async_node_add(entry->mchar); - entry->mchar_value_node_id = mchar_async_node_add(entry->mchar); + entry->mchar = mchar_async_create(); + if(entry->mchar == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + if((status = mchar_async_init(entry->mchar, 128, (4096 * 5)))) + return status; + + /* init data nodes for save input char* */ + entry->mchar_node_id = mchar_async_node_add(entry->mchar, &status); + if(status) + return status; + + entry->mchar_value_node_id = mchar_async_node_add(entry->mchar, &status); + if(status) + return status; entry->parser_list = mycss_entry_parser_list_create_and_init(128); @@ -58,7 +72,7 @@ mystatus_t mycss_entry_init(mycss_t* mycss, mycss_entry_t* entry) if(entry->selectors == NULL) return MyCSS_STATUS_ERROR_SELECTORS_CREATE; - mystatus_t status = mycss_selectors_init(entry, entry->selectors); + status = mycss_selectors_init(entry, entry->selectors); if(status != MyCSS_STATUS_OK) return status; diff --git a/source/mycss/mycss.h b/source/mycss/mycss.h index b327329..4d66e51 100644 --- a/source/mycss/mycss.h +++ b/source/mycss/mycss.h @@ -28,14 +28,14 @@ extern "C" { #ifdef MyCSS_DEBUG #define MyCSS_DEBUG_MESSAGE(format, ...) \ - mycore_print(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) + mycore_fprintf(stderr, "DEBUG: "format"\n", ##__VA_ARGS__) #else #define MyCSS_DEBUG_MESSAGE(format, ...) #endif #ifdef DEBUG_MODE #define MyCORE_DEBUG_ERROR(format, ...) \ -mycore_print(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) +mycore_fprintf(stderr, "DEBUG ERROR: "format"\n", ##__VA_ARGS__) #else #define MyCORE_DEBUG_ERROR(format, ...) #endif diff --git a/source/myencoding/Makefile.mk b/source/myencoding/Makefile.mk index dd22be0..9f31378 100644 --- a/source/myencoding/Makefile.mk +++ b/source/myencoding/Makefile.mk @@ -1,12 +1,10 @@ -find_files_h = $(wildcard $(SRCDIR)/myencoding/$(dir)/*.h) -find_files_c = $(wildcard $(SRCDIR)/myencoding/$(dir)/*.c) +myencoding_dirs := . +myencoding_objs := $(call MODEST_UTILS_OBJS,myencoding,$(myencoding_dirs)) -SUBDIRS := . -HDRS += $(foreach dir,$(SUBDIRS),$(find_files_h)) -SRCS += $(foreach dir,$(SUBDIRS),$(find_files_c)) +myencoding_all: $(myencoding_objs) -myencoding_clone: MyENCODING_DIR_$(SUBDIRS) +myencoding_clean: + rm -f $(myencoding_objs) -MyENCODING_DIR_$(SUBDIRS): - mkdir -p $(INCLUDE_TMP)/myencoding/$(patsubst MyENCODING_DIR_%,%,$@) - cp $(SRCDIR)/myencoding/$(patsubst MyENCODING_DIR_%,%,$@)/*.h $(INCLUDE_TMP)/myencoding/$(patsubst MyENCODING_DIR_%,%,$@)/ +myencoding_clone: + $(call MODEST_UTILS_HDRS_CLONE,myencoding,$(myencoding_dirs)) diff --git a/source/myfont/Makefile.mk b/source/myfont/Makefile.mk index 273d845..b8cdffc 100644 --- a/source/myfont/Makefile.mk +++ b/source/myfont/Makefile.mk @@ -1,14 +1,10 @@ -find_files_h = $(wildcard $(SRCDIR)/myfont/$(dir)/*.h) -find_files_c = $(wildcard $(SRCDIR)/myfont/$(dir)/*.c) +myfont_dirs := . +myfont_objs := $(call MODEST_UTILS_OBJS,myfont,$(myfont_dirs)) -SUBDIRS := . -HDRS += $(foreach dir,$(SUBDIRS),$(find_files_h)) -SRCS += $(foreach dir,$(SUBDIRS),$(find_files_c)) +myfont_all: $(myfont_objs) -myfont_clone: MyFONT_DIR_$(SUBDIRS) - mkdir -p $(INCLUDE_TMP)/myfont - cp $(SRCDIR)/myfont/*.h $(INCLUDE_TMP)/myfont +myfont_clean: + rm -f $(myfont_objs) -MyFONT_DIR_$(SUBDIRS): - mkdir -p $(INCLUDE_TMP)/myfont/$(patsubst MyFONT_DIR_%,%,$@) - cp $(SRCDIR)/myfont/$(patsubst MyFONT_DIR_%,%,$@)/*.h $(INCLUDE_TMP)/myfont/$(patsubst MyFONT_DIR_%,%,$@)/ +myfont_clone: + $(call MODEST_UTILS_HDRS_CLONE,myfont,$(myfont_dirs)) diff --git a/source/myfont/myfont.c b/source/myfont/myfont.c index 32e567c..1a91b05 100644 --- a/source/myfont/myfont.c +++ b/source/myfont/myfont.c @@ -37,8 +37,19 @@ myfont_font_t * myfont_create(void) mystatus_t myfont_init(myfont_font_t *mf) { - mf->mchar = mchar_async_create(64, (4096 * 2)); - mf->mchar_node_id = mchar_async_node_add(mf->mchar); + mystatus_t status; + + mf->mchar = mchar_async_create(); + if(mf->mchar == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; + + if((status = mchar_async_init(mf->mchar, 64, (4096 * 2)))) + return status; + + mf->mchar_node_id = mchar_async_node_add(mf->mchar, &status); + + if(status) + return status; memset(mf->cache.tables_offset, 0, sizeof(uint32_t) * MyFONT_TKEY_LAST_KEY); memset(&mf->header, 0, sizeof(myfont_header_t)); diff --git a/source/myhtml/Makefile.mk b/source/myhtml/Makefile.mk index 1f2e11a..e67c236 100644 --- a/source/myhtml/Makefile.mk +++ b/source/myhtml/Makefile.mk @@ -1,12 +1,10 @@ -find_files_h = $(wildcard $(SRCDIR)/myhtml/$(dir)/*.h) -find_files_c = $(wildcard $(SRCDIR)/myhtml/$(dir)/*.c) +myhtml_dirs := . +myhtml_objs := $(call MODEST_UTILS_OBJS,myhtml,$(myhtml_dirs)) -SUBDIRS := . -HDRS += $(foreach dir,$(SUBDIRS),$(find_files_h)) -SRCS += $(foreach dir,$(SUBDIRS),$(find_files_c)) +myhtml_all: $(myhtml_objs) -myhtml_clone: MyHTML_DIR_$(SUBDIRS) +myhtml_clean: + rm -f $(myhtml_objs) -MyHTML_DIR_$(SUBDIRS): - mkdir -p $(INCLUDE_TMP)/myhtml/$(patsubst MyHTML_DIR_%,%,$@) - cp $(SRCDIR)/myhtml/$(patsubst MyHTML_DIR_%,%,$@)/*.h $(INCLUDE_TMP)/myhtml/$(patsubst MyHTML_DIR_%,%,$@)/ +myhtml_clone: + $(call MODEST_UTILS_HDRS_CLONE,myhtml,$(myhtml_dirs)) diff --git a/source/myhtml/api.h b/source/myhtml/api.h index 0c54fcd..c07b6f3 100755 --- a/source/myhtml/api.h +++ b/source/myhtml/api.h @@ -1724,10 +1724,11 @@ myhtml_token_node_is_close_self(myhtml_token_node_t *token_node); /** * Wait for process token all parsing stage. Need if you use thread mode * + * @param[in] myhtml_token_t* * @param[in] myhtml_token_node_t* */ void -myhtml_token_node_wait_for_done(myhtml_token_node_t* node); +myhtml_token_node_wait_for_done(myhtml_token_t* token, myhtml_token_node_t* node); /*********************************************************************************** * diff --git a/source/myhtml/myhtml.c b/source/myhtml/myhtml.c index a95c6dc..74f05d0 100644 --- a/source/myhtml/myhtml.c +++ b/source/myhtml/myhtml.c @@ -34,89 +34,149 @@ void myhtml_destroy_marker(myhtml_t* myhtml) mycore_free(myhtml->marker); } +#ifndef MyCORE_BUILD_WITHOUT_THREADS +mystatus_t myhtml_stream_create(myhtml_t* myhtml, mystatus_t* status, size_t count, size_t id_increase) +{ + if(count == 0) { + myhtml->thread_stream = NULL; + + *status = MyHTML_STATUS_OK; + return *status; + } + + myhtml->thread_stream = mythread_create(); + if(myhtml->thread_stream == NULL) + *status = MyCORE_STATUS_THREAD_ERROR_MEMORY_ALLOCATION; + + *status = mythread_init(myhtml->thread_stream, MyTHREAD_TYPE_STREAM, count, id_increase); + + if(*status) + myhtml->thread_stream = mythread_destroy(myhtml->thread_stream, NULL, NULL, true); + + return *status; +} + +mystatus_t myhtml_batch_create(myhtml_t* myhtml, mystatus_t* status, size_t count, size_t id_increase) +{ + if(count == 0) { + myhtml->thread_batch = NULL; + + *status = MyHTML_STATUS_OK; + return *status; + } + + myhtml->thread_batch = mythread_create(); + if(myhtml->thread_stream == NULL) { + myhtml->thread_stream = mythread_destroy(myhtml->thread_stream, NULL, NULL, true); + *status = MyCORE_STATUS_THREAD_ERROR_MEMORY_ALLOCATION; + } + + *status = mythread_init(myhtml->thread_batch, MyTHREAD_TYPE_BATCH, count, id_increase); + + if(*status) + myhtml->thread_batch = mythread_destroy(myhtml->thread_batch , NULL, NULL, true); + + return *status; +} + +mystatus_t myhtml_create_stream_and_batch(myhtml_t* myhtml, size_t stream_count, size_t batch_count) +{ + mystatus_t status; + + /* stream */ + if(myhtml_stream_create(myhtml, &status, stream_count, 0)) { + return status; + } + + /* batch */ + if(myhtml_batch_create(myhtml, &status, batch_count, stream_count)) { + myhtml->thread_stream = mythread_destroy(myhtml->thread_stream, NULL, NULL, true); + return status; + } + + return status; +} +#endif /* if undef MyCORE_BUILD_WITHOUT_THREADS */ + myhtml_t * myhtml_create(void) { - return (myhtml_t*)mycore_malloc(sizeof(myhtml_t)); + return (myhtml_t*)mycore_calloc(1, sizeof(myhtml_t)); } mystatus_t myhtml_init(myhtml_t* myhtml, enum myhtml_options opt, size_t thread_count, size_t queue_size) { mystatus_t status; + myhtml->opt = opt; myhtml_init_marker(myhtml); status = myhtml_tokenizer_state_init(myhtml); - if(status) { - myhtml->insertion_func = NULL; - myhtml->thread = NULL; - - return status; - } - - status = myhtml_rules_init(myhtml); - if(status) { - myhtml->thread = NULL; - - return status; - } - - myhtml->opt = opt; - myhtml->thread = mythread_create(); - - if(myhtml->thread == NULL) - return MyCORE_STATUS_THREAD_ERROR_MEMORY_ALLOCATION; - -#ifdef MyHTML_BUILD_WITHOUT_THREADS - - status = mythread_init(myhtml->thread, NULL, thread_count); - if(status) return status; -#else /* MyHTML_BUILD_WITHOUT_THREADS */ + status = myhtml_rules_init(myhtml); + +#ifdef MyCORE_BUILD_WITHOUT_THREADS + + myhtml->thread_stream = NULL; + myhtml->thread_batch = NULL; + myhtml->thread_total = 0; + +#else /* if undef MyCORE_BUILD_WITHOUT_THREADS */ + if(status) + return status; + switch (opt) { case MyHTML_OPTIONS_PARSE_MODE_SINGLE: - status = mythread_init(myhtml->thread, "lastmac", 0); - if(status) - return status; - - myhtml->thread->context = mythread_queue_list_create(&status); - if(status) + if((status = myhtml_create_stream_and_batch(myhtml, 0, 0))) return status; break; case MyHTML_OPTIONS_PARSE_MODE_ALL_IN_ONE: - status = mythread_init(myhtml->thread, "lastmac", 1); - if(status) + if((status = myhtml_create_stream_and_batch(myhtml, 1, 0))) return status; - myhtml->thread->context = mythread_queue_list_create(&status); - if(status) - return status; + myhtml->thread_stream->context = mythread_queue_list_create(&status); + status = myhread_entry_create(myhtml->thread_stream, mythread_function_queue_stream, myhtml_parser_worker_stream, MyTHREAD_OPT_STOP); - myhread_create_stream(myhtml->thread, mythread_function_queue_stream, myhtml_parser_worker_stream, MyTHREAD_OPT_STOP, &status); break; default: // default MyHTML_OPTIONS_PARSE_MODE_SEPARATELY - if(thread_count == 0) - thread_count = 1; + if(thread_count < 2) + thread_count = 2; - status = mythread_init(myhtml->thread, "lastmac", (thread_count + 1)); + if((status = myhtml_create_stream_and_batch(myhtml, 1, (thread_count - 1)))) + return status; + + myhtml->thread_stream->context = mythread_queue_list_create(&status); + myhtml->thread_batch->context = myhtml->thread_stream->context; + + status = myhread_entry_create(myhtml->thread_stream, mythread_function_queue_stream, myhtml_parser_stream, MyTHREAD_OPT_STOP); if(status) return status; - myhtml->thread->context = mythread_queue_list_create(&status); - if(status) - return status; + for(size_t i = 0; i < myhtml->thread_batch->entries_size; i++) { + status = myhread_entry_create(myhtml->thread_batch, mythread_function_queue_batch, myhtml_parser_worker, MyTHREAD_OPT_STOP); + + if(status) + return status; + } - myhread_create_stream(myhtml->thread, mythread_function_queue_stream, myhtml_parser_stream, MyTHREAD_OPT_STOP, &status); - myhread_create_batch(myhtml->thread, mythread_function_queue_batch, myhtml_parser_worker, MyTHREAD_OPT_STOP, &status, thread_count); break; } -#endif /* MyHTML_BUILD_WITHOUT_THREADS */ + myhtml->thread_total = thread_count; + + myhtml->thread_list[0] = myhtml->thread_stream; + myhtml->thread_list[1] = myhtml->thread_batch; + myhtml->thread_list[2] = NULL; + +#endif /* if undef MyCORE_BUILD_WITHOUT_THREADS */ + + if(status) + return status; myhtml_clean(myhtml); @@ -125,7 +185,7 @@ mystatus_t myhtml_init(myhtml_t* myhtml, enum myhtml_options opt, size_t thread_ void myhtml_clean(myhtml_t* myhtml) { - mythread_clean(myhtml->thread); + /* some code */ } myhtml_t* myhtml_destroy(myhtml_t* myhtml) @@ -135,17 +195,22 @@ myhtml_t* myhtml_destroy(myhtml_t* myhtml) myhtml_destroy_marker(myhtml); - if(myhtml->thread) { -#ifndef MyHTML_BUILD_WITHOUT_THREADS - mythread_queue_list_t* queue_list = myhtml->thread->context; -#endif +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(myhtml->thread_stream) { + mythread_queue_list_t* queue_list = myhtml->thread_stream->context; + + if(queue_list) + mythread_queue_list_wait_for_done(myhtml->thread_stream, queue_list); - myhtml->thread = mythread_destroy(myhtml->thread, mythread_queue_wait_all_for_done, true); + myhtml->thread_stream = mythread_destroy(myhtml->thread_stream, mythread_callback_quit, NULL, true); -#ifndef MyHTML_BUILD_WITHOUT_THREADS - mythread_queue_list_destroy(queue_list); -#endif + if(myhtml->thread_batch) + myhtml->thread_batch = mythread_destroy(myhtml->thread_batch, mythread_callback_quit, NULL, true); + + if(queue_list) + mythread_queue_list_destroy(queue_list); } +#endif /* if undef MyCORE_BUILD_WITHOUT_THREADS */ myhtml_tokenizer_state_destroy(myhtml); @@ -1437,7 +1502,7 @@ mystatus_t myhtml_queue_add(myhtml_tree_t *tree, size_t begin, myhtml_token_node } } -#ifndef MyHTML_BUILD_WITHOUT_THREADS +#ifndef MyCORE_BUILD_WITHOUT_THREADS if(tree->flags & MyHTML_TREE_FLAGS_SINGLE_MODE) { if(qnode && token) { @@ -1447,31 +1512,30 @@ mystatus_t myhtml_queue_add(myhtml_tree_t *tree, size_t begin, myhtml_token_node myhtml_parser_stream(0, qnode); } - tree->current_qnode = mythread_queue_node_malloc_limit(tree->myhtml->thread, tree->queue, 4, NULL); + tree->current_qnode = mythread_queue_node_malloc_limit(tree->myhtml->thread_stream, tree->queue, 4, NULL); } else { if(qnode) qnode->args = token; - tree->current_qnode = mythread_queue_node_malloc_round(tree->myhtml->thread, tree->queue_entry, NULL); + tree->current_qnode = mythread_queue_node_malloc_round(tree->myhtml->thread_stream, tree->queue_entry, NULL); } #else if(qnode && token) { - qnode->token = token; + qnode->args = token; myhtml_parser_worker(0, qnode); myhtml_parser_stream(0, qnode); } - tree->current_qnode = mythread_queue_node_malloc_limit(tree->myhtml->thread, tree->queue, 4, NULL); + tree->current_qnode = mythread_queue_node_malloc_limit(tree->myhtml->thread_stream, tree->queue, 4, NULL); -#endif /* MyHTML_BUILD_WITHOUT_THREADS */ +#endif /* MyCORE_BUILD_WITHOUT_THREADS */ - if(tree->current_qnode == NULL) { + if(tree->current_qnode == NULL) return MyHTML_STATUS_ERROR_MEMORY_ALLOCATION; - } tree->current_qnode->context = tree; tree->current_qnode->prev = qnode; @@ -1480,7 +1544,6 @@ mystatus_t myhtml_queue_add(myhtml_tree_t *tree, size_t begin, myhtml_token_node myhtml_tokenizer_calc_current_namespace(tree, token); tree->current_token_node = myhtml_token_node_create(tree->token, tree->token->mcasync_token_id); - if(tree->current_token_node == NULL) return MyHTML_STATUS_ERROR_MEMORY_ALLOCATION; diff --git a/source/myhtml/myhtml.h b/source/myhtml/myhtml.h index 25672f6..2b0d353 100644 --- a/source/myhtml/myhtml.h +++ b/source/myhtml/myhtml.h @@ -30,7 +30,7 @@ extern "C" { #include "mycore/utils/mctree.h" #include "mycore/utils/mcobject_async.h" -#include "mycore/thread.h" +#include "mycore/mythread.h" #include "mycore/incoming.h" #include "myencoding/encoding.h" #include "myhtml/tree.h" @@ -65,8 +65,10 @@ extern "C" { (onechar < 'A' || onechar > 'Z')) struct myhtml { - mythread_t *thread; - //mchar_async_t *mchar; // for all + mythread_t* thread_stream; + mythread_t* thread_batch; + mythread_t* thread_list[3]; + size_t thread_total; myhtml_tokenizer_state_f* parse_state_func; myhtml_insertion_f* insertion_func; @@ -215,21 +217,6 @@ bool myhtml_is_html_node(myhtml_tree_node_t *node, myhtml_tag_id_t tag_id); // queue mystatus_t myhtml_queue_add(myhtml_tree_t *tree, size_t begin, myhtml_token_node_t* token); -/** - * Platform-specific hdef performance clock queries. - * Implemented in perf.c - */ - -/** Get clock resolution */ -uint64_t myhtml_hperf_res(mystatus_t *status); - -/** Get current value in clock ticks */ -uint64_t myhtml_hperf_clock(mystatus_t *status); - -/** Print an hperf measure */ -mystatus_t myhtml_hperf_print(const char *name, uint64_t x, uint64_t y, FILE *fh); -mystatus_t myhtml_hperf_print_by_val(const char *name, uint64_t x, FILE *fh); - /* version */ myhtml_version_t myhtml_version(void); diff --git a/source/myhtml/parser.c b/source/myhtml/parser.c index 888f0ac..a0fba3d 100644 --- a/source/myhtml/parser.c +++ b/source/myhtml/parser.c @@ -215,11 +215,17 @@ void myhtml_parser_worker(mythread_id_t thread_id, void* ctx) return; } + size_t mchar_node_id; +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(tree->myhtml->thread_batch) + mchar_node_id = tree->async_args[(thread_id + tree->myhtml->thread_batch->id_increase)].mchar_node_id; + else +#endif + mchar_node_id = tree->async_args[thread_id].mchar_node_id; + if(tree->callback_before_token) tree->callback_before_token_ctx = tree->callback_before_token(tree, token, tree->callback_before_token_ctx); - size_t mchar_node_id = tree->async_args[thread_id].mchar_node_id; - if(token->tag_id == MyHTML_TAG__TEXT || token->tag_id == MyHTML_TAG__COMMENT) { diff --git a/source/myhtml/rules.c b/source/myhtml/rules.c index 8adc78b..17da9ed 100644 --- a/source/myhtml/rules.c +++ b/source/myhtml/rules.c @@ -20,15 +20,15 @@ #include "myhtml/rules.h" -void myhtml_insertion_fix_emit_for_text_begin_ws(myhtml_token_node_t* token) +void myhtml_insertion_fix_emit_for_text_begin_ws(myhtml_token_t* token, myhtml_token_node_t* node) { - myhtml_token_node_wait_for_done(token); - mycore_string_crop_whitespace_from_begin(&token->str); + myhtml_token_node_wait_for_done(token, node); + mycore_string_crop_whitespace_from_begin(&node->str); } myhtml_token_node_t * myhtml_insertion_fix_split_for_text_begin_ws(myhtml_tree_t* tree, myhtml_token_node_t* token) { - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); size_t len = mycore_string_whitespace_from_begin(&token->str); if(len == 0) @@ -55,7 +55,7 @@ myhtml_token_node_t * myhtml_insertion_fix_split_for_text_begin_ws(myhtml_tree_t void myhtml_insertion_fix_for_null_char_drop_all(myhtml_tree_t* tree, myhtml_token_node_t* token) { - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); mycore_string_t *str = &token->str; size_t len = str->length; @@ -93,7 +93,7 @@ bool myhtml_insertion_mode_initial(myhtml_tree_t* tree, myhtml_token_node_t* tok return false; } - myhtml_insertion_fix_emit_for_text_begin_ws(token); + myhtml_insertion_fix_emit_for_text_begin_ws(tree->token, token); // default, other token tree->compat_mode = MyHTML_TREE_COMPAT_MODE_QUIRKS; @@ -109,7 +109,7 @@ bool myhtml_insertion_mode_initial(myhtml_tree_t* tree, myhtml_token_node_t* tok case MyHTML_TAG__DOCTYPE: { - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); myhtml_token_release_and_check_doctype_attributes(tree->token, token, &tree->doctype); @@ -183,7 +183,7 @@ bool myhtml_insertion_mode_before_html(myhtml_tree_t* tree, myhtml_token_node_t* break; } - myhtml_insertion_fix_emit_for_text_begin_ws(token); + myhtml_insertion_fix_emit_for_text_begin_ws(tree->token, token); // default, other token myhtml_tree_node_insert_root(tree, NULL, MyHTML_NAMESPACE_HTML); @@ -246,7 +246,7 @@ bool myhtml_insertion_mode_before_head(myhtml_tree_t* tree, myhtml_token_node_t* break; } - myhtml_insertion_fix_emit_for_text_begin_ws(token); + myhtml_insertion_fix_emit_for_text_begin_ws(tree->token, token); // default, other token tree->node_head = myhtml_tree_node_insert(tree, MyHTML_TAG_HEAD, MyHTML_NAMESPACE_HTML); @@ -1207,8 +1207,8 @@ bool myhtml_insertion_mode_in_body(myhtml_tree_t* tree, myhtml_token_node_t* tok myhtml_tree_node_t* top_node = tree->open_elements->list[0]; if(top_node->token) { - myhtml_token_node_wait_for_done(token); - myhtml_token_node_wait_for_done(top_node->token); + myhtml_token_node_wait_for_done(tree->token, token); + myhtml_token_node_wait_for_done(tree->token, top_node->token); myhtml_token_node_attr_copy_with_check(tree->token, token, top_node->token, tree->mcasync_rules_attr_id); } else { @@ -1259,8 +1259,8 @@ bool myhtml_insertion_mode_in_body(myhtml_tree_t* tree, myhtml_token_node_t* tok myhtml_tree_node_t* top_node = tree->open_elements->list[1]; if(top_node->token) { - myhtml_token_node_wait_for_done(token); - myhtml_token_node_wait_for_done(top_node->token); + myhtml_token_node_wait_for_done(tree->token, token); + myhtml_token_node_wait_for_done(tree->token, top_node->token); myhtml_token_node_attr_copy_with_check(tree->token, token, top_node->token, tree->mcasync_rules_attr_id); } else { @@ -1701,7 +1701,7 @@ bool myhtml_insertion_mode_in_body(myhtml_tree_t* tree, myhtml_token_node_t* tok myhtml_tree_node_insert_html_element(tree, token); myhtml_tree_open_elements_pop(tree); - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); if(myhtml_token_attr_match_case(tree->token, token, "type", 4, "hidden", 6) == NULL) { tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK); } @@ -1902,7 +1902,7 @@ bool myhtml_insertion_mode_in_body(myhtml_tree_t* tree, myhtml_token_node_t* tok { myhtml_tree_active_formatting_reconstruction(tree); - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); myhtml_token_adjust_mathml_attributes(token); myhtml_token_adjust_foreign_attributes(token); @@ -1920,7 +1920,7 @@ bool myhtml_insertion_mode_in_body(myhtml_tree_t* tree, myhtml_token_node_t* tok { myhtml_tree_active_formatting_reconstruction(tree); - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); myhtml_token_adjust_svg_attributes(token); myhtml_token_adjust_foreign_attributes(token); @@ -2182,7 +2182,8 @@ bool myhtml_insertion_mode_in_table(myhtml_tree_t* tree, myhtml_token_node_t* to case MyHTML_TAG_INPUT: { - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); + if(myhtml_token_attr_match_case(tree->token, token, "type", 4, "hidden", 6) == NULL) { tree->foster_parenting = true; myhtml_insertion_mode_in_body(tree, token); @@ -3396,7 +3397,7 @@ bool myhtml_insertion_mode_in_frameset(myhtml_tree_t* tree, myhtml_token_node_t* // parse error /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */ - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); mycore_string_stay_only_whitespace(&token->str); if(token->str.length) @@ -3488,7 +3489,7 @@ bool myhtml_insertion_mode_after_frameset(myhtml_tree_t* tree, myhtml_token_node // parse error /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */ - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); mycore_string_stay_only_whitespace(&token->str); if(token->str.length) @@ -3684,7 +3685,7 @@ bool myhtml_insertion_mode_in_foreign_content_start_other(myhtml_tree_t* tree, m { myhtml_tree_node_t* adjusted_node = myhtml_tree_adjusted_current_node(tree); - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); if(adjusted_node->ns == MyHTML_NAMESPACE_MATHML) { myhtml_token_adjust_mathml_attributes(token); @@ -3738,7 +3739,7 @@ bool myhtml_insertion_mode_in_foreign_content(myhtml_tree_t* tree, myhtml_token_ // parse error /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:NULL_CHAR LEVEL:ERROR */ - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); myhtml_token_set_replacement_character_for_null_token(tree, token); } @@ -3812,12 +3813,14 @@ bool myhtml_insertion_mode_in_foreign_content(myhtml_tree_t* tree, myhtml_token_ if(token->tag_id == MyHTML_TAG_FONT) { - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); if(myhtml_token_attr_by_name(token, "color", 5) == NULL && myhtml_token_attr_by_name(token, "face" , 4) == NULL && myhtml_token_attr_by_name(token, "size" , 4) == NULL) + { return myhtml_insertion_mode_in_foreign_content_start_other(tree, token); + } } if(tree->fragment == NULL) { @@ -3854,7 +3857,7 @@ bool myhtml_rules_check_for_first_newline(myhtml_tree_t* tree, myhtml_token_node if(tree->flags &MyHTML_TREE_FLAGS_PARSE_FLAG_EMIT_NEWLINE) { if(token->tag_id == MyHTML_TAG__TEXT) { - myhtml_token_node_wait_for_done(token); + myhtml_token_node_wait_for_done(tree->token, token); if(token->str.length > 0) { if(token->str.data[0] == '\n') { diff --git a/source/myhtml/tag.c b/source/myhtml/tag.c index aa94550..7a761f9 100755 --- a/source/myhtml/tag.c +++ b/source/myhtml/tag.c @@ -28,6 +28,8 @@ myhtml_tag_t * myhtml_tag_create(void) mystatus_t myhtml_tag_init(myhtml_tree_t *tree, myhtml_tag_t *tags) { + mystatus_t status; + tags->mcsimple_context = mcsimple_create(); if(tags->mcsimple_context == NULL) @@ -35,10 +37,16 @@ mystatus_t myhtml_tag_init(myhtml_tree_t *tree, myhtml_tag_t *tags) mcsimple_init(tags->mcsimple_context, 128, 1024, sizeof(myhtml_tag_context_t)); - tags->mchar_node = mchar_async_node_add(tree->mchar); - tags->tree = mctree_create(2); - tags->mchar = tree->mchar; - tags->tags_count = MyHTML_TAG_LAST_ENTRY; + tags->mchar_node = mchar_async_node_add(tree->mchar, &status); + tags->tree = mctree_create(2); + tags->mchar = tree->mchar; + tags->tags_count = MyHTML_TAG_LAST_ENTRY; + + if(status) + return status; + + if(tags->tree == NULL) + return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION; myhtml_tag_clean(tags); diff --git a/source/myhtml/token.c b/source/myhtml/token.c index ce371a8..db0d911 100644 --- a/source/myhtml/token.c +++ b/source/myhtml/token.c @@ -253,16 +253,18 @@ bool myhtml_token_node_is_close_self(myhtml_token_node_t *token_node) return (token_node->type & MyHTML_TOKEN_TYPE_CLOSE_SELF); } -void myhtml_token_node_wait_for_done(myhtml_token_node_t* node) +void myhtml_token_node_wait_for_done(myhtml_token_t* token, myhtml_token_node_t* node) { -#ifndef MyHTML_BUILD_WITHOUT_THREADS - - const struct timespec timeout = {0, 0}; - while((node->type & MyHTML_TOKEN_TYPE_DONE) == 0) {mycore_thread_nanosleep(&timeout);} - +#ifndef MyCORE_BUILD_WITHOUT_THREADS + while((node->type & MyHTML_TOKEN_TYPE_DONE) == 0) {mythread_nanosleep_sleep(token->tree->myhtml->thread_stream->timespec);} #endif } +void myhtml_token_set_done(myhtml_token_node_t* node) +{ + node->type |= MyHTML_TOKEN_TYPE_DONE; +} + myhtml_token_node_t * myhtml_token_node_clone(myhtml_token_t* token, myhtml_token_node_t* node, size_t token_thread_idx, size_t attr_thread_idx) { if(node == NULL) @@ -803,8 +805,8 @@ myhtml_token_attr_t * myhtml_token_attr_remove_by_name(myhtml_token_node_t* node myhtml_token_node_t * myhtml_token_merged_two_token_string(myhtml_tree_t* tree, myhtml_token_node_t* token_to, myhtml_token_node_t* token_from, bool cp_reverse) { - myhtml_token_node_wait_for_done(token_to); - myhtml_token_node_wait_for_done(token_from); + myhtml_token_node_wait_for_done(tree->token, token_to); + myhtml_token_node_wait_for_done(tree->token, token_from); mycore_string_t *string1 = &token_to->str; mycore_string_t *string2 = &token_from->str; @@ -855,7 +857,7 @@ myhtml_token_node_t * myhtml_token_merged_two_token_string(myhtml_tree_t* tree, void myhtml_token_set_replacement_character_for_null_token(myhtml_tree_t* tree, myhtml_token_node_t* node) { - myhtml_token_node_wait_for_done(node); + myhtml_token_node_wait_for_done(tree->token, node); mycore_string_t new_str; mycore_string_init(tree->mchar, tree->mchar_node_id, &new_str, (node->str.length + 2)); @@ -865,11 +867,6 @@ void myhtml_token_set_replacement_character_for_null_token(myhtml_tree_t* tree, node->str = new_str; } -void myhtml_token_set_done(myhtml_token_node_t* node) -{ - node->type |= MyHTML_TOKEN_TYPE_DONE; -} - void myhtml_token_print_param_by_idx(myhtml_tree_t* myhtml_tree, myhtml_token_node_t* node, FILE* out) { if(node->type & MyHTML_TOKEN_TYPE_CLOSE) { diff --git a/source/myhtml/token.h b/source/myhtml/token.h index b2b6fc9..5d7b629 100644 --- a/source/myhtml/token.h +++ b/source/myhtml/token.h @@ -130,7 +130,7 @@ myhtml_token_attr_t * myhtml_token_attr_remove_by_name(myhtml_token_node_t* node void myhtml_token_attr_delete_all(myhtml_token_t* token, myhtml_token_node_t* node); void myhtml_token_delete(myhtml_token_t* token, myhtml_token_node_t* node); -void myhtml_token_node_wait_for_done(myhtml_token_node_t* node); +void myhtml_token_node_wait_for_done(myhtml_token_t* token, myhtml_token_node_t* node); void myhtml_token_set_done(myhtml_token_node_t* node); myhtml_token_attr_t * myhtml_token_attr_match(myhtml_token_t* token, myhtml_token_node_t* target, const char* key, size_t key_size, const char* value, size_t value_size); diff --git a/source/myhtml/tokenizer.c b/source/myhtml/tokenizer.c index cd91b5d..d05402f 100644 --- a/source/myhtml/tokenizer.c +++ b/source/myhtml/tokenizer.c @@ -50,7 +50,7 @@ mystatus_t myhtml_tokenizer_chunk_process(myhtml_tree_t* tree, const char* html, // add for a chunk tree->incoming_buf = mycore_incoming_buffer_add(tree->incoming_buf, tree->mcobject_incoming_buf, html, html_length); -#ifndef MyHTML_BUILD_WITHOUT_THREADS +#ifndef MyCORE_BUILD_WITHOUT_THREADS if(myhtml->opt & MyHTML_OPTIONS_PARSE_MODE_SINGLE) tree->flags |= MyHTML_TREE_FLAGS_SINGLE_MODE; @@ -59,7 +59,9 @@ mystatus_t myhtml_tokenizer_chunk_process(myhtml_tree_t* tree, const char* html, { if(tree->queue_entry == NULL) { mystatus_t status = MyHTML_STATUS_OK; - tree->queue_entry = mythread_queue_list_entry_push(myhtml->thread, tree->queue, &status); + tree->queue_entry = mythread_queue_list_entry_push(myhtml->thread_list, 2, + myhtml->thread_stream->context, tree->queue, + myhtml->thread_total, &status); if(status) return status; @@ -172,19 +174,22 @@ mystatus_t myhtml_tokenizer_end(myhtml_tree_t* tree) mystatus_t status = tree->tokenizer_status; -#ifndef MyHTML_BUILD_WITHOUT_THREADS +#ifndef MyCORE_BUILD_WITHOUT_THREADS if((tree->flags & MyHTML_TREE_FLAGS_SINGLE_MODE) == 0) { - mythread_queue_list_entry_wait_for_done(tree->myhtml->thread, tree->queue_entry); - tree->queue_entry = mythread_queue_list_entry_delete(tree->myhtml->thread, tree->queue_entry, false); + mythread_queue_list_entry_wait_for_done(tree->myhtml->thread_stream, tree->queue_entry); + + tree->queue_entry = mythread_queue_list_entry_delete(tree->myhtml->thread_list, 2, + tree->myhtml->thread_stream->context, + tree->queue_entry, false); + /* Further, any work with tree... */ - if(mythread_queue_list_get_count(tree->myhtml->thread->context) == 0) { + if(mythread_queue_list_get_count(tree->myhtml->thread_stream->context) == 0) myhtml_tokenizer_pause(tree); - } if(status == MyHTML_STATUS_OK) - status = mythread_check_status(tree->myhtml->thread); + status = mythread_check_status(tree->myhtml->thread_stream); } #endif @@ -238,17 +243,32 @@ myhtml_tree_node_t * myhtml_tokenizer_fragment_init(myhtml_tree_t* tree, myhtml_ void myhtml_tokenizer_wait(myhtml_tree_t* tree) { - mythread_queue_wait_all_for_done(tree->myhtml->thread); +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(tree->myhtml->thread_stream) + mythread_queue_list_entry_wait_for_done(tree->myhtml->thread_stream, tree->queue_entry); +#endif } void myhtml_tokenizer_post(myhtml_tree_t* tree) { - mythread_resume_all(tree->myhtml->thread); +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(tree->myhtml->thread_stream) + mythread_resume(tree->myhtml->thread_stream); + + if(tree->myhtml->thread_batch) + mythread_resume(tree->myhtml->thread_batch); +#endif } void myhtml_tokenizer_pause(myhtml_tree_t* tree) { - mythread_stop_all(tree->myhtml->thread); +#ifndef MyCORE_BUILD_WITHOUT_THREADS + if(tree->myhtml->thread_stream) + mythread_stop(tree->myhtml->thread_stream); + + if(tree->myhtml->thread_batch) + mythread_stop(tree->myhtml->thread_batch); +#endif } void myhtml_tokenizer_calc_current_namespace(myhtml_tree_t* tree, myhtml_token_node_t* token_node) diff --git a/source/myhtml/tokenizer.h b/source/myhtml/tokenizer.h index 9a5784f..c5b7219 100644 --- a/source/myhtml/tokenizer.h +++ b/source/myhtml/tokenizer.h @@ -28,7 +28,7 @@ extern "C" { #include "myhtml/myosi.h" #include "mycore/utils.h" -#include "mycore/thread.h" +#include "mycore/mythread.h" #include "myhtml/myhtml.h" #include "myhtml/tag.h" #include "myhtml/tokenizer_doctype.h" diff --git a/source/myhtml/tree.c b/source/myhtml/tree.c index 8233dbc..f39835d 100644 --- a/source/myhtml/tree.c +++ b/source/myhtml/tree.c @@ -38,7 +38,6 @@ mystatus_t myhtml_tree_init(myhtml_tree_t* tree, myhtml_t* myhtml) tree->temp_tag_name.data = NULL; tree->stream_buffer = NULL; tree->parse_flags = MyHTML_TREE_PARSE_FLAGS_CLEAN; - tree->queue = mythread_queue_create(9182, &status); tree->context = NULL; tree->callback_before_token = NULL; @@ -54,7 +53,16 @@ mystatus_t myhtml_tree_init(myhtml_tree_t* tree, myhtml_t* myhtml) if(status) return status; - /* init Incoming Buffer objects */ + /* Thread Queue */ + tree->queue = mythread_queue_create(); + if(tree->queue == NULL) + return MyHTML_STATUS_ERROR_MEMORY_ALLOCATION; + + status = mythread_queue_init(tree->queue, 9182); + if(status) + return status; + + /* Init Incoming Buffer objects */ tree->mcobject_incoming_buf = mcobject_create(); if(tree->mcobject_incoming_buf == NULL) return MyHTML_STATUS_TREE_ERROR_INCOMING_BUFFER_CREATE; @@ -72,13 +80,19 @@ mystatus_t myhtml_tree_init(myhtml_tree_t* tree, myhtml_t* myhtml) if(mcstatus) return MyHTML_STATUS_TREE_ERROR_MCOBJECT_INIT; - tree->mchar = mchar_async_create(128, (4096 * 5)); + tree->mchar = mchar_async_create(); tree->active_formatting = myhtml_tree_active_formatting_init(tree); tree->open_elements = myhtml_tree_open_elements_init(tree); tree->other_elements = myhtml_tree_list_init(); tree->token_list = myhtml_tree_token_list_init(); tree->template_insertion = myhtml_tree_template_insertion_init(tree); + if(tree->mchar == NULL) + return MyHTML_STATUS_ERROR_MEMORY_ALLOCATION; + + if((status = mchar_async_init(tree->mchar, 128, (4096 * 5)))) + return status; + tree->mcasync_tree_id = mcobject_async_node_add(tree->tree_obj, &mcstatus); if(mcstatus) return MyHTML_STATUS_TREE_ERROR_MCOBJECT_CREATE_NODE; @@ -91,36 +105,40 @@ mystatus_t myhtml_tree_init(myhtml_tree_t* tree, myhtml_t* myhtml) if(mcstatus) return MyHTML_STATUS_TREE_ERROR_MCOBJECT_CREATE_NODE; - tree->mchar_node_id = mchar_async_node_add(tree->mchar); - -#ifndef MyHTML_BUILD_WITHOUT_THREADS - - tree->async_args = (myhtml_async_args_t*)mycore_calloc(myhtml->thread->pth_list_length, sizeof(myhtml_async_args_t)); - +#ifndef MyCORE_BUILD_WITHOUT_THREADS + tree->async_args = (myhtml_async_args_t*)mycore_calloc(myhtml->thread_total, sizeof(myhtml_async_args_t)); if(tree->async_args == NULL) - return MyHTML_STATUS_TREE_ERROR_MEMORY_ALLOCATION; - - // for single mode in main thread - tree->async_args[0].mchar_node_id = tree->mchar_node_id; + return MyHTML_STATUS_ERROR_MEMORY_ALLOCATION; // for batch thread - for(size_t i = 0; i < myhtml->thread->batch_count; i++) { - tree->async_args[(myhtml->thread->batch_first_id + i)].mchar_node_id = mchar_async_node_add(tree->mchar); + for(size_t i = 0; i < myhtml->thread_total; i++) { + tree->async_args[i].mchar_node_id = mchar_async_node_add(tree->mchar, &status); + + if(status) + return status; } - -#else /* MyHTML_BUILD_WITHOUT_THREADS */ - +#else /* MyCORE_BUILD_WITHOUT_THREADS */ tree->async_args = (myhtml_async_args_t*)mycore_calloc(1, sizeof(myhtml_async_args_t)); if(tree->async_args == NULL) return MyHTML_STATUS_TREE_ERROR_MEMORY_ALLOCATION; - tree->async_args->mchar_node_id = tree->mchar_node_id; + tree->async_args->mchar_node_id = mchar_async_node_add(tree->mchar, &status); -#endif /* MyHTML_BUILD_WITHOUT_THREADS */ + if(status) + return status; + +#endif /* MyCORE_BUILD_WITHOUT_THREADS */ + + /* for main thread only after parsing */ + tree->mchar_node_id = tree->async_args->mchar_node_id; tree->sync = mcsync_create(); - mcsync_init(tree->sync); + if(tree->sync == NULL) + return MyHTML_STATUS_ERROR_MEMORY_ALLOCATION; + + if(mcsync_init(tree->sync)) + return MyHTML_STATUS_ERROR_MEMORY_ALLOCATION; /* init Tags after create and init mchar */ tree->tags = myhtml_tag_create(); @@ -133,22 +151,23 @@ mystatus_t myhtml_tree_init(myhtml_tree_t* tree, myhtml_t* myhtml) void myhtml_tree_clean(myhtml_tree_t* tree) { -#ifndef MyHTML_BUILD_WITHOUT_THREADS +#ifndef MyCORE_BUILD_WITHOUT_THREADS myhtml_t* myhtml = tree->myhtml; - for(size_t i = 0; i < myhtml->thread->batch_count; i++) { - mchar_async_node_clean(tree->mchar, tree->async_args[(myhtml->thread->batch_first_id + i)].mchar_node_id); + for(size_t i = 0; i < myhtml->thread_total; i++) { + mchar_async_node_clean(tree->mchar, tree->async_args[i].mchar_node_id); } -#endif /* MyHTML_BUILD_WITHOUT_THREADS */ +#else + mchar_async_node_clean(tree->mchar, tree->mchar_node_id); +#endif mcobject_async_node_clean(tree->tree_obj, tree->mcasync_tree_id); mcobject_async_node_clean(tree->token->nodes_obj, tree->mcasync_rules_token_id); mcobject_async_node_clean(tree->token->attr_obj, tree->mcasync_rules_attr_id); - mchar_async_node_clean(tree->mchar, tree->mchar_node_id); -#ifndef MyHTML_BUILD_WITHOUT_THREADS - mythread_queue_list_entry_clean(tree->myhtml->thread, tree->queue_entry); -#endif /* MyHTML_BUILD_WITHOUT_THREADS */ +#ifndef MyCORE_BUILD_WITHOUT_THREADS + mythread_queue_list_entry_clean(tree->queue_entry); +#endif /* MyCORE_BUILD_WITHOUT_THREADS */ myhtml_token_clean(tree->token); @@ -252,9 +271,9 @@ void myhtml_tree_clean_all(myhtml_tree_t* tree) mcobject_clean(tree->mcobject_incoming_buf); myhtml_tag_clean(tree->tags); -#ifndef MyHTML_BUILD_WITHOUT_THREADS - mythread_queue_list_entry_clean(tree->myhtml->thread, tree->queue_entry); -#endif /* MyHTML_BUILD_WITHOUT_THREADS */ +#ifndef MyCORE_BUILD_WITHOUT_THREADS + mythread_queue_list_entry_clean(tree->queue_entry); +#endif tree->attr_current = myhtml_token_attr_create(tree->token, tree->token->mcasync_attr_id); } @@ -493,7 +512,7 @@ myhtml_tree_node_t * myhtml_tree_node_clone(myhtml_tree_node_t* node) { myhtml_tree_node_t* new_node = myhtml_tree_node_create(node->tree); - myhtml_token_node_wait_for_done(node->token); + myhtml_token_node_wait_for_done(node->tree->token, node->token); new_node->token = myhtml_token_node_clone(node->tree->token, node->token, node->tree->mcasync_rules_token_id, @@ -1424,8 +1443,8 @@ void myhtml_tree_active_formatting_append_with_check(myhtml_tree_t* tree, myhtml if(list[i]->token && node->token) { - myhtml_token_node_wait_for_done(list[i]->token); - myhtml_token_node_wait_for_done(node->token); + myhtml_token_node_wait_for_done(tree->token, list[i]->token); + myhtml_token_node_wait_for_done(tree->token, node->token); if(list[i]->ns == node->ns && list[i]->tag_id == node->tag_id && @@ -2443,7 +2462,7 @@ bool myhtml_tree_is_html_integration_point(myhtml_tree_t* tree, myhtml_tree_node node->tag_id == MyHTML_TAG_ANNOTATION_XML && node->token && (node->token->type & MyHTML_TOKEN_TYPE_CLOSE) == 0) { - myhtml_token_node_wait_for_done(node->token); + myhtml_token_node_wait_for_done(tree->token, node->token); myhtml_token_attr_t* attr = myhtml_token_attr_match_case(tree->token, node->token, "encoding", 8, "text/html", 9); @@ -2540,10 +2559,9 @@ mystatus_t myhtml_tree_temp_tag_name_append(myhtml_tree_temp_tag_name_t* temp_ta void myhtml_tree_wait_for_last_done_token(myhtml_tree_t* tree, myhtml_token_node_t* token_for_wait) { -#ifndef MyHTML_BUILD_WITHOUT_THREADS +#ifndef MyCORE_BUILD_WITHOUT_THREADS - const struct timespec timeout = {0, 0}; - while(tree->token_last_done != token_for_wait) {mycore_thread_nanosleep(&timeout);} + while(tree->token_last_done != token_for_wait) {mythread_nanosleep_sleep(tree->myhtml->thread_stream->timespec);} #endif } diff --git a/source/myhtml/tree.h b/source/myhtml/tree.h index ea9d553..e98ad44 100644 --- a/source/myhtml/tree.h +++ b/source/myhtml/tree.h @@ -31,6 +31,7 @@ extern "C" { #include "myhtml/mystring.h" #include "myhtml/token.h" #include "myhtml/stream.h" +#include "mycore/thread_queue.h" #include "mycore/utils/mcsync.h" #include "mycore/utils/mchar_async.h" #include "mycore/utils/mcobject.h" @@ -185,6 +186,11 @@ struct myhtml_tree { size_t mcasync_rules_token_id; size_t mcasync_rules_attr_id; size_t mcasync_tree_id; + /* + * mchar_node_id + * for rules, or if single mode, + * or for main thread only after parsing + */ size_t mchar_node_id; myhtml_token_attr_t* attr_current; myhtml_tag_id_t tmp_tag_id; @@ -227,7 +233,7 @@ struct myhtml_tree { volatile myhtml_tree_parse_flags_t parse_flags; bool foster_parenting; size_t global_offset; - mystatus_t tokenizer_status; + mystatus_t tokenizer_status; myencoding_t encoding; myencoding_t encoding_usereq; diff --git a/source/myport/posix/Makefile.mk b/source/myport/posix/Makefile.mk new file mode 100644 index 0000000..4581590 --- /dev/null +++ b/source/myport/posix/Makefile.mk @@ -0,0 +1,9 @@ +myport_dirs := mycore/. mycore/utils +myport_objs := $(call MODEST_UTILS_OBJS,myport/$(strip $(MODEST_PORT_NAME)),$(myport_dirs)) + +myport_all: $(myport_objs) + +myport_clean: + rm -f $(myport_objs) + +myport_clone: diff --git a/source/myport/posix/mycore/io.c b/source/myport/posix/mycore/io.c new file mode 100644 index 0000000..2a6a4e0 --- /dev/null +++ b/source/myport/posix/mycore/io.c @@ -0,0 +1,91 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/myosi.h" +#include + +int mycore_printf(const char* format, ...) +{ + va_list argptr; + va_start(argptr, format); + int res = vprintf(format, argptr); + va_end(argptr); + + return res; +} + +int mycore_fprintf(FILE* out, const char* format, ...) +{ + va_list argptr; + va_start(argptr, format); + int res = vfprintf(out, format, argptr); + va_end(argptr); + + return res; +} + +int mycore_snprintf(char* buffer, size_t buffer_size, const char* format, ...) +{ + va_list argptr; + va_start(argptr, format); + int res = vsnprintf(buffer, buffer_size, format, argptr); + va_end(argptr); + + return res; +} + +/* FILE */ +FILE * mycore_fopen(const char *restrict filename, const char *restrict mode) +{ + return fopen(filename, mode); +} + +int mycore_fclose(FILE *stream) +{ + return fclose(stream); +} + +size_t mycore_fread(void *restrict buffer, size_t size, size_t count, FILE *restrict stream) +{ + return fread(buffer, size, count, stream); +} + +size_t mycore_fwrite(const void *restrict buffer, size_t size, size_t count, FILE *restrict stream) +{ + return fwrite(buffer, size, count, stream); +} + +int mycore_fflush(FILE *stream) +{ + return fflush(stream); +} + +int mycore_ferror(FILE *stream) +{ + return ferror(stream); +} + +/* setbuf */ +void mycore_setbuf(FILE *restrict stream, char *restrict buffer) +{ + return setbuf(stream, buffer); +} + + diff --git a/source/myport/posix/mycore/memory.c b/source/myport/posix/mycore/memory.c new file mode 100644 index 0000000..4cfd1e0 --- /dev/null +++ b/source/myport/posix/mycore/memory.c @@ -0,0 +1,42 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/myosi.h" + +void * mycore_malloc(size_t size) +{ + return malloc(size); +} + +void * mycore_realloc(void* dst, size_t size) +{ + return realloc(dst, size); +} + +void * mycore_calloc(size_t num, size_t size) +{ + return calloc(num, size); +} + +void * mycore_free(void* dst) +{ + free(dst); + return NULL; +} diff --git a/source/mycore/perf.c b/source/myport/posix/mycore/perf.c similarity index 100% rename from source/mycore/perf.c rename to source/myport/posix/mycore/perf.c diff --git a/source/myport/posix/mycore/thread.c b/source/myport/posix/mycore/thread.c new file mode 100644 index 0000000..d4e753b --- /dev/null +++ b/source/myport/posix/mycore/thread.c @@ -0,0 +1,156 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/mythread.h" +#include "mycore/utils/mcsync.h" + +#ifndef MyCORE_BUILD_WITHOUT_THREADS +#include + +/*********************************************************************************** + * + * For all unix system. POSIX pthread + * + ***********************************************************************************/ +void * mythread_thread_create(mythread_t *mythread, void* process_func, void* ctx) +{ + pthread_t thread; + + if(pthread_create(&thread, mythread->attr, process_func, ctx) == 0) + return thread; + + return NULL; +} + +mystatus_t mythread_thread_join(mythread_t *mythread, void* thread) +{ + if(pthread_join(thread, NULL) == 0) + return MyCORE_STATUS_OK; + + return MyCORE_STATUS_ERROR; +} + +mystatus_t mythread_thread_cancel(mythread_t *mythread, void* thread) +{ + if(pthread_cancel(thread) == 0) + return MyCORE_STATUS_OK; + + return MyCORE_STATUS_ERROR; +} + +mystatus_t mythread_thread_destroy(mythread_t *mythread, void* thread) +{ + return MyCORE_STATUS_OK; +} + +void * mythread_thread_attr_init(mythread_t *mythread) +{ + pthread_attr_t *attr = (pthread_attr_t*)mycore_calloc(1, sizeof(pthread_attr_t)); + + if(attr == NULL) + return NULL; + + mythread->sys_last_error = pthread_attr_init(attr); + if(mythread->sys_last_error) { + mycore_free(attr); + return NULL; + } + + mythread->sys_last_error = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_JOINABLE); + if(mythread->sys_last_error) { + mycore_free(attr); + return NULL; + } + + return attr; +} + +void mythread_thread_attr_clean(mythread_t *mythread, void* attr) +{ + /* some code */ +} + +void mythread_thread_attr_destroy(mythread_t *mythread, void* attr) +{ + if(attr == NULL) + return; + + mythread->sys_last_error = pthread_attr_destroy(attr); + mycore_free(attr); +} + +void * mythread_mutex_create(mythread_t *mythread) +{ + void *mutex = mcsync_mutex_create(); + if(mutex == NULL) + return NULL; + + if(mcsync_mutex_init(mutex)) { + mycore_free(mutex); + return NULL; + } + + return mutex; +} + +mystatus_t mythread_mutex_post(mythread_t *mythread, void* mutex) +{ + return mcsync_mutex_unlock(mutex); +} + +mystatus_t mythread_mutex_wait(mythread_t *mythread, void* mutex) +{ + return mcsync_mutex_lock(mutex); +} + +mystatus_t mythread_mutex_try_wait(mythread_t *mythread, void* mutex) +{ + return mcsync_mutex_try_lock(mutex); +} + +void mythread_mutex_close(mythread_t *mythread, void* mutex) +{ + mcsync_mutex_destroy(mutex); +} + +void * mythread_nanosleep_create(mythread_t* mythread) +{ + return mycore_calloc(1, sizeof(struct timespec)); +} + +void mythread_nanosleep_clean(void* timespec) +{ + memset(timespec, 0, sizeof(struct timespec)); +} + +void mythread_nanosleep_destroy(void* timespec) +{ + mycore_free(timespec); +} + +mystatus_t mythread_nanosleep_sleep(void* timespec) +{ + if(nanosleep(timespec, NULL) == 0) + return MyCORE_STATUS_OK; + + return MyCORE_STATUS_ERROR; +} + +#endif diff --git a/source/myport/posix/mycore/utils/mcsync.c b/source/myport/posix/mycore/utils/mcsync.c new file mode 100644 index 0000000..6544a55 --- /dev/null +++ b/source/myport/posix/mycore/utils/mcsync.c @@ -0,0 +1,154 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/utils/mcsync.h" + +#ifndef MyCORE_BUILD_WITHOUT_THREADS +#include + +#if ((defined(__GNUC__) && __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__ATOMIC_SEQ_CST)) +#define MyCORE_MCSYNC_SPINLOCK_PRESENT +#endif + +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT +static mcsync_status_t mcsync_static_atomic_lock(void* spinlock) +{ + int compare = 0; + while (!__atomic_compare_exchange_n((int*)spinlock, &compare, 1, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {} + + return MCSYNC_STATUS_OK; +} + +static mcsync_status_t mcsync_static_atomic_unlock(void* spinlock) +{ + __atomic_store_n((int*)spinlock, 0, __ATOMIC_SEQ_CST); + + return MCSYNC_STATUS_OK; +} +#endif /* MyCORE_MCSYNC_SPINLOCK_PRESENT */ + +/* spinlock */ +void * mcsync_spin_create(void) +{ + return mycore_calloc(1, sizeof(int)); +} + +mcsync_status_t mcsync_spin_init(void* spinlock) +{ +#ifndef MyCORE_MCSYNC_SPINLOCK_PRESENT + return mcsync_mutex_init(spinlock); +#else + return MCSYNC_STATUS_OK; +#endif +} + +void mcsync_spin_clean(void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + *((int*)spinlock) = 0; +#endif +} + +void mcsync_spin_destroy(void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + mycore_free(spinlock); +#else + mcsync_mutex_destroy(spinlock); +#endif +} + +mcsync_status_t mcsync_spin_lock(void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + return mcsync_static_atomic_lock(spinlock); +#else + return mcsync_mutex_lock(spinlock); +#endif +} + +mcsync_status_t mcsync_spin_unlock(void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + return mcsync_static_atomic_unlock(spinlock); +#else + return mcsync_mutex_unlock(spinlock); +#endif +} + +/* mutex */ +void * mcsync_mutex_create(void) +{ + void *mutex = mycore_calloc(1, sizeof(pthread_mutex_t)); + if(mutex == NULL) + return mutex; + + if(pthread_mutex_init(mutex, NULL)) + return mycore_free(mutex); + + return mutex; +} + +mcsync_status_t mcsync_mutex_init(void* mutex) +{ + if(pthread_mutex_init(mutex, NULL)) { + mycore_free(mutex); + return MCSYNC_STATUS_NOT_OK; + } + + return MCSYNC_STATUS_OK; +} + +void mcsync_mutex_clean(void* mutex) +{ + /* clean function */ +} + +void mcsync_mutex_destroy(void* mutex) +{ + pthread_mutex_destroy(mutex); + mycore_free(mutex); +} + +mcsync_status_t mcsync_mutex_lock(void* mutex) +{ + if(pthread_mutex_lock(mutex) == 0) + return MCSYNC_STATUS_OK; + + return MCSYNC_STATUS_NOT_OK; +} + +mcsync_status_t mcsync_mutex_try_lock(void* mutex) +{ + if(pthread_mutex_trylock(mutex) == 0) + return MCSYNC_STATUS_OK; + + return MCSYNC_STATUS_NOT_OK; +} + +mcsync_status_t mcsync_mutex_unlock(void* mutex) +{ + if(pthread_mutex_unlock(mutex) == 0) + return MCSYNC_STATUS_OK; + + return MCSYNC_STATUS_NOT_OK; +} + +#endif diff --git a/source/myport/windows/mycore/io.c b/source/myport/windows/mycore/io.c new file mode 100644 index 0000000..2a6a4e0 --- /dev/null +++ b/source/myport/windows/mycore/io.c @@ -0,0 +1,91 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/myosi.h" +#include + +int mycore_printf(const char* format, ...) +{ + va_list argptr; + va_start(argptr, format); + int res = vprintf(format, argptr); + va_end(argptr); + + return res; +} + +int mycore_fprintf(FILE* out, const char* format, ...) +{ + va_list argptr; + va_start(argptr, format); + int res = vfprintf(out, format, argptr); + va_end(argptr); + + return res; +} + +int mycore_snprintf(char* buffer, size_t buffer_size, const char* format, ...) +{ + va_list argptr; + va_start(argptr, format); + int res = vsnprintf(buffer, buffer_size, format, argptr); + va_end(argptr); + + return res; +} + +/* FILE */ +FILE * mycore_fopen(const char *restrict filename, const char *restrict mode) +{ + return fopen(filename, mode); +} + +int mycore_fclose(FILE *stream) +{ + return fclose(stream); +} + +size_t mycore_fread(void *restrict buffer, size_t size, size_t count, FILE *restrict stream) +{ + return fread(buffer, size, count, stream); +} + +size_t mycore_fwrite(const void *restrict buffer, size_t size, size_t count, FILE *restrict stream) +{ + return fwrite(buffer, size, count, stream); +} + +int mycore_fflush(FILE *stream) +{ + return fflush(stream); +} + +int mycore_ferror(FILE *stream) +{ + return ferror(stream); +} + +/* setbuf */ +void mycore_setbuf(FILE *restrict stream, char *restrict buffer) +{ + return setbuf(stream, buffer); +} + + diff --git a/source/mycore/memory.c b/source/myport/windows/mycore/memory.c similarity index 100% rename from source/mycore/memory.c rename to source/myport/windows/mycore/memory.c diff --git a/source/myport/windows/mycore/perf.c b/source/myport/windows/mycore/perf.c new file mode 100644 index 0000000..38c397b --- /dev/null +++ b/source/myport/windows/mycore/perf.c @@ -0,0 +1,288 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Authors: insoreiges@gmail.com (Evgeny Yakovlev), lex.borisov@gmail.com (Alexander Borisov) +*/ + +/** + * Platform-specific hdef performance clock value. + */ + +#include "mycore/myosi.h" +#include + +#if !defined(IS_OS_WINDOWS) +#include +#endif + +#if !defined(MyCORE_WITH_PERF) + +uint64_t mycore_hperf_res(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_PERF_ERROR_COMPILED_WITHOUT_PERF; + + return 0; +} + +uint64_t mycore_hperf_clock(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_PERF_ERROR_COMPILED_WITHOUT_PERF; + + return 0; +} + +#else + +#if defined(__APPLE__) +#include +#include +#elif defined(IS_OS_WINDOWS) +#endif + +#if defined(MyCORE_FORCE_RDTSC) /* Force using rdtsc, useful for comparison */ + +/** + * Get CPU rdtsc frequency. + * + * TODO: I think using rdtsc for measuring user-space counters is not correct: + * - rdtsc does not have a constant rate. instead ot is scaled to physical core's internal clock which changes due to power saving modes on modern CPUs + * - rdtsc is software-emulated in virtual machines which will introduce an inconsistency in reported ticks + * - user space process can be preempted between consecutive rdtsc measures but the physical clock will still tick while it is executing a different thread. + * also think what would happen if preempted process will be re-scheduled on a different physical core which has a different tsc value. + * - computing rdtsc frequency produces unreliable results (due to all of the above) + * + * Consider using platform-specific monotonic hperf timers (ftrace/dtrace) or even clock(). + */ +uint64_t mycore_hperf_res(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_OK; + +#if defined(__APPLE__) && defined(CTL_HW) && defined(HW_CPU_FREQ) + unsigned long long freq = 0; + + /* OSX kernel: sysctl(CTL_HW | HW_CPU_FREQ) */ + size_t len = sizeof(freq); + int mib[2] = {CTL_HW, HW_CPU_FREQ}; + + int error = sysctl(mib, 2, &freq, &len, NULL, 0); + if (error) { + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; + } + + return freq; + +#elif defined(__linux__) + unsigned long long freq = 0; + + /* Use procfs on linux */ + FILE* fp = NULL; + fp = fopen("/proc/cpuinfo", "r"); + if (fp == NULL) { + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; + } + + /* Find 'CPU MHz :' */ + char buf[1024] = {0}; + double fval = 0.0; + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (sscanf(buf, "cpu MHz : %lf\n", &fval) == 1) { + freq = (unsigned long long)(fval * 1000000ull); + break; + } + } + + fclose(fp); + return freq; + +#else +# warning Cant figure out cpu frequency on this platfrom + + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; +#endif /* defined __APPLE__ || __linux__ ... */ +} + +uint64_t mycore_hperf_clock(mystatus_t *status) +{ + uint64_t x; + + __asm__ volatile ( + "cpuid\n\t" /* cpuid serializes any out-of-order prefetches before executing rdtsc (clobbers ebx, ecx, edx) */ + "rdtsc\n\t" + "shl $32, %%rdx\n\t" + "or %%rdx, %%rax" + : "=a" (x) + : + : "rdx", "ebx", "ecx"); + + return x; +} + +#elif defined(_POSIX_TIMERS) && defined(_POSIX_CPUTIME) \ + && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) /* Do we have clock_gettime? */ + +#define NSEC_PER_SECOND 1000000000ull +#define TIMESPEC_TO_USEC(tspec) (((uint64_t)(tspec).tv_sec * NSEC_PER_SECOND) + (tspec).tv_nsec) + +uint64_t mycore_hperf_res(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_OK; + + struct timespec tspec; + int error = clock_getres(CLOCK_PROCESS_CPUTIME_ID, &tspec); + if (error) { + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; + } + + unsigned long long ticks_per_sec = (unsigned long long)((double)NSEC_PER_SECOND / TIMESPEC_TO_USEC(tspec)); + return ticks_per_sec; +} + +uint64_t mycore_hperf_clock(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_OK; + + struct timespec tspec; + int error = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tspec); + if (error) { + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; + } + + return TIMESPEC_TO_USEC(tspec); +} + +#elif defined(__APPLE__) && defined(__MACH__) + +/* + * TODO: on OSX we can use clock_get_time: http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x + * Or this: http://web.archive.org/web/20100517095152/http://www.wand.net.nz/~smr26/wordpress/2009/01/19/monotonic-time-in-mac-os-x/comment-page-1/ + */ + +// TODO: this is incorrect plug for mac os x +// look at links before this comment + +#include + +uint64_t mycore_hperf_res(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_OK; + + unsigned long long freq = 0; + + size_t len = sizeof(freq); + int mib[2] = {CTL_HW, HW_CPU_FREQ}; + + int error = sysctl(mib, 2, &freq, &len, NULL, 0); + if (error) { + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; + } + + return freq; +} + +uint64_t mycore_hperf_clock(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_OK; + + return mach_absolute_time(); +} + +#else + +# warning No hperf implementation for this platform + +uint64_t mycore_hperf_res(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; +} + +uint64_t mycore_hperf_clock(mystatus_t *status) +{ + if(status) + *status = MyCORE_STATUS_PERF_ERROR_FIND_CPU_CLOCK; + + return 0; +} + +#endif /* defined(MyCORE_FORCE_RDTSC) ... */ +#endif /* MyCORE_WITH_PERF */ + +#define _MyCORE_CHECK_STATUS_AND_PRINT_ERROR \ + if(status == MyCORE_STATUS_PERF_ERROR_COMPILED_WITHOUT_PERF) { \ + fprintf(fh, "MyCORE: Library compiled without perf source. Please, build library with -DMyCORE_WITH_PERF flag\n"); \ + } \ + else if(status) { \ + fprintf(fh, "MyCORE: Something wrong! Perhaps, your platform does not support the measurement of performance\n"); \ + } \ + else + +mystatus_t mycore_hperf_print(const char *name, uint64_t x, uint64_t y, FILE *fh) { + mystatus_t status; + + unsigned long long freq = mycore_hperf_res(&status); + + if(freq) { + _MyCORE_CHECK_STATUS_AND_PRINT_ERROR { + fprintf(fh, "%s: %0.5f\n", name, (((float)(y - x) / (float)freq))); + } + } + + return status; +} + +mystatus_t mycore_hperf_print_by_val(const char *name, uint64_t x, FILE *fh) { + mystatus_t status; + + unsigned long long freq = mycore_hperf_res(&status); + + if(freq) { + _MyCORE_CHECK_STATUS_AND_PRINT_ERROR { + fprintf(fh, "%s: %0.5f\n", name, ((float)x / (float)freq)); + } + } + + return status; +} + + diff --git a/source/myport/windows/mycore/thread.c b/source/myport/windows/mycore/thread.c new file mode 100644 index 0000000..ae0d6d0 --- /dev/null +++ b/source/myport/windows/mycore/thread.c @@ -0,0 +1,109 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/mythread.h" + +#ifndef MyCORE_BUILD_WITHOUT_THREADS +/*********************************************************************************** + * + * For Windows + * + ***********************************************************************************/ +mystatus_t mycore_thread_create(mythread_t *mythread, mythread_list_t *thr, void *work_func) +{ + thr->pth = CreateThread(NULL, // default security attributes + 0, // use default stack size + work_func, // thread function name + &thr->data, // argument to thread function + 0, // use default creation flags + NULL); // returns the thread identifier + + + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_thread_join(mythread_t *mythread, mythread_list_t *thr) +{ + WaitForSingleObject(thr->pth, INFINITE); + + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_thread_cancel(mythread_t *mythread, mythread_list_t *thr) +{ + TerminateThread(thr->pth, 0); + + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_thread_attr_init(mythread_t *mythread) +{ + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_thread_attr_clean(mythread_t *mythread) +{ + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_thread_attr_destroy(mythread_t *mythread) +{ + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_hread_mutex_create(mythread_t *mythread, mythread_context_t *ctx, size_t prefix_id) +{ + ctx->mutex = CreateSemaphore(NULL, 0, 1, NULL); + + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_hread_mutex_post(mythread_t *mythread, mythread_context_t *ctx) +{ + ReleaseSemaphore(ctx->mutex, 1, NULL); + + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_hread_mutex_wait(mythread_t *mythread, mythread_context_t *ctx) +{ + WaitForSingleObject(ctx->mutex, INFINITE); + + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_hread_mutex_try_wait(mythread_t *mythread, mythread_context_t *ctx) +{ + return MyCORE_STATUS_OK; +} + +mystatus_t mycore_hread_mutex_close(mythread_t *mythread, mythread_context_t *ctx) +{ + CloseHandle(ctx->mutex); + + return MyCORE_STATUS_OK; +} + +void mycore_thread_nanosleep(const struct timespec *tomeout) +{ + Sleep(0); +} + +#endif diff --git a/source/myport/windows/mycore/utils/mcsync.c b/source/myport/windows/mycore/utils/mcsync.c new file mode 100644 index 0000000..607211d --- /dev/null +++ b/source/myport/windows/mycore/utils/mcsync.c @@ -0,0 +1,144 @@ +/* + Copyright (C) 2015-2017 Alexander Borisov + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Author: lex.borisov@gmail.com (Alexander Borisov) +*/ + +#include "mycore/utils/mcsync.h" +#include + +#if ((defined(__GNUC__) && __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__ATOMIC_SEQ_CST)) +#define MyCORE_MCSYNC_SPINLOCK_PRESENT +#endif + +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT +static mcsync_status_t mcsync_static_atomic_lock(void* spinlock) +{ + int compare = 0; + while (!__atomic_compare_exchange_n(spinlock, &compare, 1, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {} + + return MCSYNC_STATUS_OK; +} + +static mcsync_status_t mcsync_static_atomic_unlock(void* spinlock) +{ + __atomic_store_n(spinlock, 0, __ATOMIC_SEQ_CST); + + return MCSYNC_STATUS_OK; +} +#endif /* MyCORE_MCSYNC_SPINLOCK_PRESENT */ + +/* spinlock */ +void * mcsync_spin_init(void) +{ + return mycore_calloc(1, sizeof(int)); +} + +mcsync_status_t mcsync_spin_init(void* spinlock) +{ +#ifndef MyCORE_MCSYNC_SPINLOCK_PRESENT + return mcsync_mutex_init(spinlock); +#else + return MCSYNC_STATUS_OK; +#endif +} + +void mcsync_spin_clean(void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + *((int*)spinlock) = 0; +#endif +} + +void mcsync_spin_destroy(void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + mcsync_spin_clean(spinlock); +#else + mcsync_mutex_destroy(spinlock); +#endif +} + +mcsync_status_t mcsync_spin_lock((void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + return mcsync_static_atomic_lock(spinlock); +#else + return mcsync_mutex_lock(spinlock); +#endif +} + +mcsync_status_t mcsync_spin_unlock((void* spinlock) +{ +#ifdef MyCORE_MCSYNC_SPINLOCK_PRESENT + return mcsync_static_atomic_unlock(spinlock); +#else + return mcsync_mutex_unlock(spinlock); +#endif +} + +/* mutex */ +void * mcsync_mutex_create(void) +{ + void *mutex = mycore_calloc(1, sizeof(pthread_mutex_t)); + if(mutex == NULL) + return mutex; + + if(pthread_mutex_init(mutex, NULL)) + return mycore_free(mutex); + + return mutex; +} + +mcsync_status_t mcsync_mutex_init(void) +{ + if(pthread_mutex_init(mutex, NULL)) { + mycore_free(mutex); + return MCSYNC_STATUS_NOT_OK; + } + + return MCSYNC_STATUS_OK; +} + +void mcsync_mutex_clean(void* mutex) +{ + /* clean function */ +} + +void mcsync_mutex_destroy(void* mutex) +{ + pthread_mutex_destroy(mutex); + mycore_free(mutex); +} + +mcsync_status_t mcsync_mutex_lock(void* mutex) +{ + if(pthread_mutex_lock(mutex) == 0) + return MCSYNC_STATUS_OK; + + return MCSYNC_STATUS_NOT_OK; +} + +mcsync_status_t mcsync_mutex_unlock(void* mutex) +{ + if(pthread_mutex_unlock(mutex) == 0) + return MCSYNC_STATUS_OK; + + return MCSYNC_STATUS_NOT_OK; +} + + diff --git a/source/myunicode/Makefile.mk b/source/myunicode/Makefile.mk new file mode 100644 index 0000000..35d955b --- /dev/null +++ b/source/myunicode/Makefile.mk @@ -0,0 +1,10 @@ +myunicode_dirs := . +myunicode_objs := $(call MODEST_UTILS_OBJS,myunicode,$(myunicode_dirs)) + +myunicode_all: $(myunicode_objs) + +myunicode_clean: + rm -f $(myunicode_objs) + +myunicode_clone: + $(call MODEST_UTILS_HDRS_CLONE,myunicode,$(myunicode_dirs)) diff --git a/source/myunicode/myosi.c b/source/myunicode/myosi.c index 0d584e5..104d2c3 100644 --- a/source/myunicode/myosi.c +++ b/source/myunicode/myosi.c @@ -22,16 +22,15 @@ void * myunicode_callback_malloc(size_t size, void* ctx) { - return myhtml_malloc(size); + return mycore_malloc(size); } void * myunicode_callback_realloc(void* value, size_t size, void* ctx) { - return myhtml_realloc(value, size); + return mycore_realloc(value, size); } void * myunicode_callback_free(void* value, void* ctx) { - free(value); - return NULL; + return mycore_free(value); } diff --git a/source/myurl/Makefile.mk b/source/myurl/Makefile.mk index d82f7c9..6b6cfee 100644 --- a/source/myurl/Makefile.mk +++ b/source/myurl/Makefile.mk @@ -1,14 +1,10 @@ -find_files_h = $(wildcard $(SRCDIR)/myurl/$(dir)/*.h) -find_files_c = $(wildcard $(SRCDIR)/myurl/$(dir)/*.c) +myurl_dirs := . +myurl_objs := $(call MODEST_UTILS_OBJS,myurl,$(myurl_dirs)) -SUBDIRS := . -HDRS += $(foreach dir,$(SUBDIRS),$(find_files_h)) -SRCS += $(foreach dir,$(SUBDIRS),$(find_files_c)) +myurl_all: $(myurl_objs) -myurl_clone: MyURL_DIR_$(SUBDIRS) - mkdir -p $(INCLUDE_TMP)/myurl - cp $(SRCDIR)/myurl/*.h $(INCLUDE_TMP)/myurl +myurl_clean: + rm -f $(myurl_objs) -MyURL_DIR_$(SUBDIRS): - mkdir -p $(INCLUDE_TMP)/myurl/$(patsubst MyURL_DIR_%,%,$@) - cp $(SRCDIR)/myurl/$(patsubst MyURL_DIR_%,%,$@)/*.h $(INCLUDE_TMP)/myurl/$(patsubst MyURL_DIR_%,%,$@)/ +myurl_clone: + $(call MODEST_UTILS_HDRS_CLONE,myurl,$(myurl_dirs))