pax_global_header00006660000000000000000000000064134353472130014517gustar00rootroot0000000000000052 comment=c63359ee0aa4fc416c336fae92d58129f315bb07 libverto-0.3.1/000077500000000000000000000000001343534721300133465ustar00rootroot00000000000000libverto-0.3.1/.autotools000066400000000000000000000027131343534721300154030ustar00rootroot00000000000000 libverto-0.3.1/.checkstyle000066400000000000000000000004371343534721300155110ustar00rootroot00000000000000 libverto-0.3.1/.cproject000066400000000000000000000640011343534721300151610ustar00rootroot00000000000000 make all true true false make am--refresh true true false make check true true false make clean true true false make clean-libtool true true false make ctags true true false make ctags-recursive true true false make dist true true false make dist-all true true false make dist-bzip2 true true false make dist-gzip true true false make dist-lzma true true false make dist-shar true true false make dist-tarZ true true false make dist-xz true true false make dist-zip true true false make distcheck true true false make distclean true true false make distclean-libtool true true false make distclean-tags true true false make distcleancheck true true false make distdir true true false make distuninstallcheck true true false make dvi true true false make html true true false make info true true false make install true true false make install-data true true false make install-dvi true true false make install-exec true true false make install-html true true false make install-info true true false make install-man true true false make install-pdf true true false make install-pkgconfigDATA true true false make install-ps true true false make install-strip true true false make installcheck true true false make installdirs true true false make libverto-glib.pc true true false make libverto-libev.pc true true false make libverto-libevent.pc true true false make libverto-tevent.pc true true false make libverto.pc true true false make maintainer-clean true true false make Makefile true true false make mostlyclean true true false make mostlyclean-libtool true true false make pdf true true false make ps true true false make tags true true false make tags-recursive true true false make uninstall true true false make uninstall-pkgconfigDATA true true false libverto-0.3.1/.gitignore000066400000000000000000000004421343534721300153360ustar00rootroot00000000000000.deps .libs aclocal.m4 autom4te.cache config.guess config.log config.status config.sub configure depcomp install-sh libtool ltmain.sh Makefile Makefile.in missing test-driver *.la *.lo *.o *.log *.pc *.trs tests/idle tests/timeout tests/child tests/signal tests/read tests/write INSTALL libverto-0.3.1/.project000066400000000000000000000041501343534721300150150ustar00rootroot00000000000000 libverto org.eclipse.linuxtools.cdt.autotools.core.genmakebuilderV2 org.eclipse.cdt.managedbuilder.core.genmakebuilder clean,full,incremental, ?name? org.eclipse.cdt.make.core.append_environment true org.eclipse.cdt.make.core.buildArguments org.eclipse.cdt.make.core.buildCommand make org.eclipse.cdt.make.core.contents org.eclipse.cdt.make.core.activeConfigSettings org.eclipse.cdt.make.core.enableAutoBuild false org.eclipse.cdt.make.core.enableCleanBuild true org.eclipse.cdt.make.core.enableFullBuild true org.eclipse.cdt.make.core.stopOnError true org.eclipse.cdt.make.core.useDefaultBuildCmd true org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder full,incremental, org.eclipse.cdt.core.cnature org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature org.eclipse.linuxtools.cdt.autotools.core.autotoolsNatureV2 libverto-0.3.1/.settings/000077500000000000000000000000001343534721300152645ustar00rootroot00000000000000libverto-0.3.1/.settings/org.eclipse.cdt.core.prefs000066400000000000000000000306511343534721300222440ustar00rootroot00000000000000#Thu Jun 09 17:23:01 EDT 2011 eclipse.preferences.version=1 org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80 org.eclipse.cdt.core.formatter.alignment_for_compact_if=0 org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80 org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16 org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48 org.eclipse.cdt.core.formatter.alignment_for_expression_list=0 org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=18 org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.cdt.core.formatter.compact_else_if=true org.eclipse.cdt.core.formatter.continuation_indentation=2 org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2 org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false org.eclipse.cdt.core.formatter.indent_empty_lines=false org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false org.eclipse.cdt.core.formatter.indentation.size=8 org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.cdt.core.formatter.lineSplit=80 org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.cdt.core.formatter.tabulation.char=space org.eclipse.cdt.core.formatter.tabulation.size=4 org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false libverto-0.3.1/.settings/org.eclipse.cdt.ui.prefs000066400000000000000000000001641343534721300217250ustar00rootroot00000000000000#Thu Jun 09 15:51:38 EDT 2011 eclipse.preferences.version=1 formatter_profile=_FreeIPA formatter_settings_version=1 libverto-0.3.1/.travis.sh000077500000000000000000000015331343534721300152750ustar00rootroot00000000000000#!/bin/bash -ex CFLAGS="-Werror" if [ x$BUILTIN == xyes ]; then CFLAGS+=" -DBUILTIN_MODULE=libev" fi if [ -f /etc/debian_version ]; then apt-get update apt-get -y install autoconf build-essential libtool $COMPILER \ lib{ev,event,glib2.0}-dev elif [ -f /etc/fedora-release ]; then # dnf has no update-only verb dnf -y install autoconf automake libtool make which $COMPILER \ {glib2,libevent,libev}-devel --nogpgcheck --skip-broken elif [ -f /etc/redhat-release ]; then # rhel/centos yum -y install autoconf automake libtool make which $COMPILER \ {glib2,libevent}-devel # rhel doesn't have libev anyway CFLAGS+=" -std=c89" else echo "Distro not found!" false fi autoreconf -fiv ./configure CFLAGS="$CFLAGS" CC=$(which $COMPILER) make if [ x$BUILTIN != xyes ]; then make check fi libverto-0.3.1/.travis.yml000066400000000000000000000007071343534721300154630ustar00rootroot00000000000000sudo: required # not necessary, but less confusing if defined language: C services: - docker env: - DISTRO=debian:sid COMPILER=gcc - DISTRO=debian:sid COMPILER=gcc BUILTIN=yes - DISTRO=fedora:latest COMPILER=gcc - DISTRO=fedora:latest COMPILER=clang - DISTRO=centos:7 COMPILER=gcc script: - > docker run -v `pwd`:/tmp/build -w /tmp/build -e COMPILER=$COMPILER -e BUILTIN=$BUILTIN $DISTRO /bin/bash -ex .travis.sh libverto-0.3.1/AUTHORS000066400000000000000000000000531343534721300144140ustar00rootroot00000000000000Nathaniel McCallum libverto-0.3.1/COPYING000066400000000000000000000020361343534721300144020ustar00rootroot00000000000000Copyright 2011 Red Hat, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libverto-0.3.1/ChangeLog000066400000000000000000000026531343534721300151260ustar00rootroot000000000000002012-08-25 Nathaniel McCallum * == Release 0.2.5 == * fix libev's set_flags() implementation * add AIX dlopen() support * export symbols based on symbol list files * add support for building in a static module * add support for specifying default module 2012-02-09 Nathaniel McCallum * == Release 0.2.4 == * add verto_set_flags() 2012-02-08 Nathaniel McCallum * == Release 0.2.3 == * add external allocator support * add extern "C" to all headers * support getting fd state in callbacks * support getting ctx from ev * add support for auto-closing file descriptors * fix a bug where we wrote to free'd memory 2011-11-11 Nathaniel McCallum * == Release 0.2.2 == * Remove trailing uses of types starting with _ * Documentation fix 2011-11-10 Nathaniel McCallum * == Release 0.2.1 == * Build system fix for broken 0.2.0 release 2011-11-10 Nathaniel McCallum * == Release 0.2.0 == * Fix inconsistent verto_default() singleton state * Give modules unique table names * Remove signal table verification magic (no longer needed) * Give verto_reinitialize() an error condition (int return value) * Add (optional) pthread locking around our global state * Cleanup the build system arguments 2011-09-30 Nathaniel McCallum * Initial release libverto-0.3.1/Makefile.am000066400000000000000000000005331343534721300154030ustar00rootroot00000000000000pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libverto.pc if MODULE_GLIB pkgconfig_DATA += libverto-glib.pc endif if MODULE_LIBEV pkgconfig_DATA += libverto-libev.pc endif if MODULE_LIBEVENT pkgconfig_DATA += libverto-libevent.pc endif if MODULE_TEVENT pkgconfig_DATA += libverto-tevent.pc endif ACLOCAL_AMFLAGS=-I m4 SUBDIRS=src tests libverto-0.3.1/NEWS000066400000000000000000000000471343534721300140460ustar00rootroot00000000000000Sample NEWS file for libverto project. libverto-0.3.1/README000066400000000000000000000011511343534721300142240ustar00rootroot00000000000000 libverto =============================================================================== libverto exists to solve an important problem: many applications and libraries are unable to write asynchronous code because they are unable to pick an event loop. This is particularly true of libraries who want to be useful to many applications who use loops that do not integrate with one another or which use home-grown loops. libverto provides a loop-neutral async api which allows the library to expose asynchronous interfaces and offload the choice of the main loop to the application. libverto-0.3.1/configure.ac000066400000000000000000000157231343534721300156440ustar00rootroot00000000000000dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) AC_INIT(libverto, 0.3.1) m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], [AC_USE_SYSTEM_EXTENSIONS], [AC_GNU_SOURCE]) AC_PROG_CC_C99 for flag in -Wall -Wextra -Wno-cast-function-type; do OLD_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $flag" AC_TRY_COMPILE(, [return 0;], [], [CFLAGS=$OLD_CFLAGS]) done AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE([1.11]) AC_PROG_LIBTOOL AC_CONFIG_MACRO_DIR([m4]) m4_ifdef([AM_SILENT_RULES], [ AM_SILENT_RULES([yes]) ], [ AM_DEFAULT_VERBOSITY=1 AC_SUBST(AM_DEFAULT_VERBOSITY) ]) PKG_PROG_PKG_CONFIG AC_CHECK_LIB([dl],[dlopen]) AC_ARG_WITH([pthread], [AS_HELP_STRING([--with-pthread], [build pthread support @<:@default: automatic@:>@])], [case $withval in no) WITH_PTHREAD=no;; yes) WITH_PTHREAD=yes;; *) WITH_PTHREAD=auto;; esac], [WITH_PTHREAD=auto]) BUILD_PTHREAD=no if test x$WITH_PTHREAD != xno; then AX_PTHREAD([PTHREAD_CFLAGS="$PTHREAD_CFLAGS -DHAVE_PTHREAD=1"; CC="$PTHREAD_CC"; BUILD_PTHREAD=yes], [test x$WITH_PTHREAD = xyes && AC_MSG_ERROR("pthread not found")]) fi AC_ARG_WITH([glib], [AS_HELP_STRING([--with-glib], [build the glib library @<:@default: automatic@:>@])], [case $withval in no) WITH_GLIB=no;; yes) WITH_GLIB=yes;; default) WITH_GLIB=default;; builtin) WITH_GLIB=builtin;; *) WITH_GLIB=auto;; esac], [WITH_GLIB=auto]) AC_ARG_WITH([libev], [AS_HELP_STRING([--with-libev], [build the libev library @<:@default: automatic@:>@])], [case $withval in no) WITH_LIBEV=no;; yes) WITH_LIBEV=yes;; default) WITH_LIBEV=default;; builtin) WITH_LIBEV=builtin;; *) WITH_LIBEV=auto;; esac], [WITH_LIBEV=auto]) AC_ARG_WITH([libevent], [AS_HELP_STRING([--with-libevent], [build the libevent library @<:@default: automatic@:>@])], [case $withval in no) WITH_LIBEVENT=no;; yes) WITH_LIBEVENT=yes;; default) WITH_LIBEVENT=default;; builtin) WITH_LIBEVENT=builtin;; *) WITH_LIBEVENT=auto;; esac], [WITH_LIBEVENT=auto]) AC_ARG_WITH([tevent], [AS_HELP_STRING([--with-tevent], [build the tevent library @<:@default: automatic@:>@])], [case $withval in no) WITH_TEVENT=no;; yes) WITH_TEVENT=yes;; *) WITH_TEVENT=auto;; esac], [WITH_TEVENT=auto]) # Ensure that if a builtin is chosen only one is built BUILTIN_MODULE= if test x$WITH_GLIB == xbuiltin; then BUILTIN_MODULE=glib WITH_LIBEV=no WITH_LIBEVENT=no WITH_TEVENT=no elif test x$WITH_LIBEV == xbuiltin; then BUILTIN_MODULE=libev WITH_LIBGLIB=no WITH_LIBEVENT=no WITH_TEVENT=no elif test x$WITH_LIBEVENT == xbuiltin; then BUILTIN_MODULE=libevent WITH_LIBGLIB=no WITH_LIBEV=no WITH_TEVENT=no elif test x$WITH_TEVENT == xbuiltin; then BUILTIN_MODULE=tevent WITH_GLIB=no WITH_LIBEV=no WITH_LIBEVENT=no fi AC_SUBST([BUILTIN_MODULE], $BUILTIN_MODULE) if test x$BUILTIN_MODULE != x; then AC_DEFINE_UNQUOTED([BUILTIN_MODULE], $BUILTIN_MODULE) fi # Ensure that there is only one default (convert duplicate default to yes) if test x$WITH_GLIB == xdefault; then AC_DEFINE([DEFUALT_MODULE], [glib]) test x$WITH_LIBEV == xdefault && WITH_LIBEV=yes test x$WITH_LIBEVENT == xdefault && WITH_LIBEVENT=yes test x$WITH_TEVENT == xdefault && WITH_TEVENT=yes fi if test x$WITH_LIBEV == xdefault; then AC_DEFINE([DEFUALT_MODULE], [libev]) test x$WITH_LIBGLIB == xdefault && WITH_GLIB=yes test x$WITH_LIBEVENT == xdefault && WITH_LIBEVENT=yes test x$WITH_TEVENT == xdefault && WITH_TEVENT=yes fi if test x$WITH_LIBEVENT == xdefault; then AC_DEFINE([DEFUALT_MODULE], [libevent]) test x$WITH_GLIB == xdefault && WITH_GLIB=yes test x$WITH_LIBEV == xdefault && WITH_LIBEV=yes test x$WITH_TEVENT == xdefault && WITH_TEVENT=yes fi if test x$WITH_TEVENT == xdefault; then AC_DEFINE([DEFUALT_MODULE], [tevent]) test x$WITH_GLIB == xdefault && WITH_GLIB=yes test x$WITH_LIBEV == xdefault && WITH_LIBEV=yes test x$WITH_LIBEVENT == xdefault && WITH_LIBEVENT=yes fi BUILD_GLIB=no BUILD_LIBEV=no BUILD_LIBEVENT=no BUILD_TEVENT=no if test x$WITH_GLIB != xno; then PKG_CHECK_MODULES([glib], [glib-2.0], [BUILD_GLIB=$WITH_GLIB], [test x$WITH_GLIB != xauto && AC_MSG_ERROR("glib not found")]) if test x$BUILD_GLIB == xauto; then BUILD_GLIB=yes fi fi if test x$WITH_LIBEV != xno; then AC_CHECK_HEADER( [ev.h], AC_CHECK_LIB( [ev], [ev_loop_new], [BUILD_LIBEV=$WITH_LIBEV], [test x$WITH_LIBEV != xauto && AC_MSG_ERROR("libev not found")] ), [test x$WITH_LIBEV != xauto && AC_MSG_ERROR("ev.h not found")] ) if test x$BUILD_LIBEV == xauto; then BUILD_LIBEV=yes fi fi if test x$WITH_LIBEVENT != xno; then PKG_CHECK_MODULES([libevent], [libevent >= 2.0], [BUILD_LIBEVENT=$WITH_LIBEVENT], [test x$WITH_LIBEVENT != xauto && AC_MSG_ERROR("libevent not found")]) if test x$BUILD_LIBEVENT == xauto; then BUILD_LIBEVENT=yes fi fi if test x$WITH_TEVENT != xno; then PKG_CHECK_MODULES([tevent], [tevent], [BUILD_TEVENT=$WITH_TEVENT], [test x$WITH_TEVENT != xauto && AC_MSG_ERROR("tevent not found")]) if test x$BUILD_TEVENT == xauto; then BUILD_TEVENT=yes fi fi AM_CONDITIONAL([MODULE_GLIB], [test x$BUILTIN_MODULE == x && test x$BUILD_GLIB != xno]) AM_CONDITIONAL([MODULE_LIBEV], [test x$BUILTIN_MODULE == x && test x$BUILD_LIBEV != xno]) AM_CONDITIONAL([MODULE_LIBEVENT], [test x$BUILTIN_MODULE == x && test x$BUILD_LIBEVENT != xno]) AM_CONDITIONAL([MODULE_TEVENT], [test x$BUILTIN_MODULE == x && test x$BUILD_TEVENT != xno]) AM_CONDITIONAL([BUILTIN_GLIB], [test x$BUILTIN_MODULE == xglib]) AM_CONDITIONAL([BUILTIN_LIBEV], [test x$BUILTIN_MODULE == xlibev]) AM_CONDITIONAL([BUILTIN_LIBEVENT], [test x$BUILTIN_MODULE == xlibevent]) AM_CONDITIONAL([BUILTIN_TEVENT], [test x$BUILTIN_MODULE == xtevent]) AC_MSG_NOTICE() AC_MSG_NOTICE([BUILD CONFIGURATION]) AC_MSG_NOTICE(AS_HELP_STRING([pthread], [$BUILD_PTHREAD])) AC_MSG_NOTICE(AS_HELP_STRING([glib], [$BUILD_GLIB])) AC_MSG_NOTICE(AS_HELP_STRING([libev], [$BUILD_LIBEV])) AC_MSG_NOTICE(AS_HELP_STRING([libevent], [$BUILD_LIBEVENT])) AC_MSG_NOTICE(AS_HELP_STRING([tevent], [$BUILD_TEVENT])) AC_MSG_NOTICE() AC_CONFIG_FILES(Makefile src/Makefile tests/Makefile libverto-glib.pc libverto-libev.pc libverto-libevent.pc libverto-tevent.pc libverto.pc) AC_OUTPUT libverto-0.3.1/libverto-glib.pc.in000066400000000000000000000004111343534721300170340ustar00rootroot00000000000000prefix=@prefix@ libdir=@libdir@ includedir=@includedir@ exec_prefix=@exec_prefix@ Name: libverto-glib Description: Event loop abstraction interface (glib module) Version: @VERSION@ Libs: -L${libdir} -lverto-glib Cflags: -I${includedir} Requires.private: libverto libverto-0.3.1/libverto-libev.pc.in000066400000000000000000000004141343534721300172230ustar00rootroot00000000000000prefix=@prefix@ libdir=@libdir@ includedir=@includedir@ exec_prefix=@exec_prefix@ Name: libverto-libev Description: Event loop abstraction interface (libev module) Version: @VERSION@ Libs: -L${libdir} -lverto-libev Cflags: -I${includedir} Requires.private: libverto libverto-0.3.1/libverto-libevent.pc.in000066400000000000000000000004251343534721300177340ustar00rootroot00000000000000prefix=@prefix@ libdir=@libdir@ includedir=@includedir@ exec_prefix=@exec_prefix@ Name: libverto-libevent Description: Event loop abstraction interface (libevent module) Version: @VERSION@ Libs: -L${libdir} -lverto-libevent Cflags: -I${includedir} Requires.private: libverto libverto-0.3.1/libverto-tevent.pc.in000066400000000000000000000004171343534721300174320ustar00rootroot00000000000000prefix=@prefix@ libdir=@libdir@ includedir=@includedir@ exec_prefix=@exec_prefix@ Name: libverto-tevent Description: Event loop abstraction interface (tevent module) Version: @VERSION@ Libs: -L${libdir} -lverto-tevent Cflags: -I${includedir} Requires.private: libverto libverto-0.3.1/libverto.pc.in000066400000000000000000000003531343534721300161260ustar00rootroot00000000000000prefix=@prefix@ libdir=@libdir@ includedir=@includedir@ exec_prefix=@exec_prefix@ Name: libverto Description: Event loop abstraction interface Version: @VERSION@ Libs: -L${libdir} -lverto Cflags: -I${includedir} Libs.private: @LIBS@ libverto-0.3.1/m4/000077500000000000000000000000001343534721300136665ustar00rootroot00000000000000libverto-0.3.1/m4/.gitignore000066400000000000000000000000161343534721300156530ustar00rootroot00000000000000* !.gitignore libverto-0.3.1/m4/ax_pthread.m4000066400000000000000000000301611343534721300162500ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. e.g. you should link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threads programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program 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 General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 16 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) AC_MSG_RESULT($ax_pthread_ok) if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; *-darwin*) ax_pthread_flags="-pthread $ax_pthread_flags" ;; esac if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($ax_pthread_ok) if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $attr; return attr /* ; */])], [attr_name=$attr; break], []) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], ax_cv_PTHREAD_PRIO_INHERIT, [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD libverto-0.3.1/src/000077500000000000000000000000001343534721300141355ustar00rootroot00000000000000libverto-0.3.1/src/Makefile.am000066400000000000000000000044541343534721300162000ustar00rootroot00000000000000AM_CFLAGS = -Wall -Wdeclaration-after-statement AM_LDFLAGS = -version-info 1:0:0 EXTRA_DIST = libverto.symbols libverto-glib.symbols libverto-libev.symbols \ libverto-libevent.symbols libverto-tevent.symbols include_HEADERS = verto.h verto-module.h noinst_HEADERS = module.h lib_LTLIBRARIES = libverto.la libverto_la_SOURCES = verto.c module.c verto.h libverto_la_CFLAGS = $(AM_CFLAGS) $($(BUILTIN_MODULE)_CFLAGS) $(PTHREAD_CFLAGS) libverto_la_LDFLAGS = $(AM_LDFLAGS) $($(BUILTIN_MODULE)_LIBS) $(PTHREAD_LIBS) $(LIBS) \ -export-symbols $(srcdir)/libverto.symbols if BUILTIN_GLIB libverto_la_SOURCES += verto-glib.c endif if BUILTIN_LIBEV libverto_la_SOURCES += verto-libev.c endif if BUILTIN_LIBEVENT libverto_la_SOURCES += verto-libevent.c endif if BUILTIN_TEVENT libverto_la_SOURCES += verto-tevent.c endif if MODULE_GLIB lib_LTLIBRARIES += libverto-glib.la include_HEADERS += verto-glib.h libverto_glib_la_SOURCES = verto-glib.c libverto_glib_la_LIBADD = libverto.la libverto_glib_la_CFLAGS = $(AM_CFLAGS) $(glib_CFLAGS) libverto_glib_la_LDFLAGS = $(AM_LDFLAGS) $(glib_LIBS) \ -export-symbols $(srcdir)/libverto-glib.symbols endif if MODULE_LIBEV lib_LTLIBRARIES += libverto-libev.la include_HEADERS += verto-libev.h libverto_libev_la_SOURCES = verto-libev.c libverto_libev_la_LIBADD = libverto.la libverto_libev_la_CFLAGS = $(AM_CFLAGS) libverto_libev_la_LDFLAGS = $(AM_LDFLAGS) -lev \ -export-symbols $(srcdir)/libverto-libev.symbols endif if MODULE_LIBEVENT lib_LTLIBRARIES += libverto-libevent.la include_HEADERS += verto-libevent.h libverto_libevent_la_SOURCES = verto-libevent.c libverto_libevent_la_LIBADD = libverto.la libverto_libevent_la_CFLAGS = $(AM_CFLAGS) $(libevent_CFLAGS) libverto_libevent_la_LDFLAGS = $(AM_LDFLAGS) $(libevent_LIBS) \ -export-symbols $(srcdir)/libverto-libevent.symbols endif if MODULE_TEVENT lib_LTLIBRARIES += libverto-tevent.la include_HEADERS += verto-tevent.h libverto_tevent_la_SOURCES = verto-tevent.c libverto_tevent_la_LIBADD = libverto.la libverto_tevent_la_CFLAGS = $(AM_CFLAGS) $(tevent_CFLAGS) libverto_tevent_la_LDFLAGS = $(AM_LDFLAGS) $(tevent_LIBS) \ -export-symbols $(srcdir)/libverto-tevent.symbols endif libverto-0.3.1/src/libverto-glib.symbols000066400000000000000000000001151343534721300203050ustar00rootroot00000000000000verto_convert_glib verto_default_glib verto_module_table_glib verto_new_glib libverto-0.3.1/src/libverto-libev.symbols000066400000000000000000000001211343534721300204660ustar00rootroot00000000000000verto_convert_libev verto_default_libev verto_module_table_libev verto_new_libev libverto-0.3.1/src/libverto-libevent.symbols000066400000000000000000000001351343534721300212020ustar00rootroot00000000000000verto_convert_libevent verto_default_libevent verto_module_table_libevent verto_new_libevent libverto-0.3.1/src/libverto-tevent.symbols000066400000000000000000000001251343534721300206760ustar00rootroot00000000000000verto_convert_tevent verto_default_tevent verto_module_table_tevent verto_new_tevent libverto-0.3.1/src/libverto.symbols000066400000000000000000000010251343534721300173730ustar00rootroot00000000000000verto_add_child verto_add_idle verto_add_io verto_add_signal verto_add_timeout verto_break verto_cleanup verto_convert_module verto_default verto_del verto_fire verto_free verto_get_ctx verto_get_fd verto_get_fd_state verto_get_flags verto_get_interval verto_get_private verto_get_proc verto_get_proc_status verto_get_signal verto_get_supported_types verto_get_type verto_new verto_reinitialize verto_run verto_run_once verto_set_allocator verto_set_default verto_set_fd_state verto_set_flags verto_set_private verto_set_proc_status libverto-0.3.1/src/module.c000066400000000000000000000131211343534721300155640ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifdef WIN32 #include #define dlltype HMODULE static char * dllerror(void) { char *amsg; LPTSTR msg; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL); amsg = strdup((const char*) msg); LocalFree(msg); return amsg; } #elif defined(aix) #include "sys/ldr.h" struct Dl_info { const char* dli_fname; }; static int dladdr(void* s, Dl_info* i) { static const size_t bufSize = 4096; G__FastAllocString buf(bufSize); char* pldi = buf; int r; r = loadquery(L_GETINFO, pldi, bufSize); if (r == -1) { i->dli_fname = NULL; return 0; } for (ld_info* ldi = (ld_info*) buf; ldi->ldinfo_next; ldi += ldi->ldinfo_next) { char* textBegin = (char*) ldi->ldinfo_textorg; if (textBegin < s) { char* textEnd = textBegin + ldi->ldinfo_textsize; if (textEnd > s) { i->dli_fname = ldi->ldinfo_filename; return 1; } } } // First is main(), skip. ld_info* ldi = (ld_info*) pldi; while (ldi->ldinfo_next) { pldi += ldi->ldinfo_next; ldi = (ld_info*) pldi; } i->dli_fname = NULL; return 0; } #else #include #include #include #define dlltype void * #define dllerror() strdup(dlerror()) #endif int module_symbol_is_present(const char *modname, const char *symbname) { #ifdef WIN32 return (GetProcAddress(GetModuleHandle(modname), symbname) != NULL || GetProcAddress(GetModuleHandle(NULL), symbname) != NULL); #else /* WIN32 */ void *mod; (void) modname; mod = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); if (mod) { void* sym = dlsym(mod, symbname); dlclose(mod); return sym != NULL; } #endif /* WIN32 */ return 0; } int module_get_filename_for_symbol(void *addr, char **filename) { #ifdef WIN32 MEMORY_BASIC_INFORMATION info; HMODULE mod; char tmp[MAX_PATH]; if (!VirtualQuery(addr, &info, sizeof(info))) return 0; mod = (HMODULE) info.AllocationBase; if (!GetModuleFileNameA(mod, tmp, MAX_PATH)) return 0; #else const char *tmp; Dl_info dlinfo; if (!dladdr(addr, &dlinfo)) return 0; tmp = dlinfo.dli_fname; #endif if (filename) { *filename = strdup(tmp); if (!*filename) return 0; } return 1; } void module_close(void *dll) { if (!dll) return; #ifdef WIN32 FreeLibrary((dlltype) dll); #else /* WIN32 */ dlclose((dlltype) dll); #endif /* WIN32 */ } char * module_load(const char *filename, const char *symbname, int (*shouldload)(void *symb, void *misc, char **err), void *misc, void **dll, void **symb) { dlltype intdll = NULL; void * intsym = NULL; char * interr = NULL; if (dll) *dll = NULL; if (symb) *symb = NULL; /* Open the module library */ #ifdef WIN32 /* NOTE: DONT_RESOLVE_DLL_REFERENCES is evil. Don't use this in your own * code. However, our design pattern avoids all the issues surrounding a * more general use of this evil flag. */ intdll = LoadLibraryEx(filename, NULL, DONT_RESOLVE_DLL_REFERENCES); #else /* WIN32 */ intdll = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); #endif /* WIN32 */ if (!intdll) goto fail; /* Get the module symbol */ #ifdef WIN32 intsym = (void *) GetProcAddress(intdll, symbname); #else /* WIN32 */ intsym = dlsym(intdll, symbname); #endif /* WIN32 */ if (!intsym) goto fail; /* Figure out whether or not to load this module */ if (!shouldload(intsym, misc, &interr)) goto fail; /* Re-open the module */ module_close(intdll); #ifdef WIN32 intdll = LoadLibrary(filename); #else /* WIN32 */ intdll = dlopen(filename, RTLD_NOW | RTLD_LOCAL); #endif /* WIN32 */ if (!intdll) goto fail; /* Get the symbol again */ #ifdef WIN32 intsym = (void *) GetProcAddress(intdll, symbname); #else /* WIN32 */ intsym = dlsym(intdll, symbname); #endif /* WIN32 */ if (!intsym) goto fail; if (dll) *dll = intdll; if (symb) *symb = intsym; return NULL; fail: if (!interr) interr = dllerror(); module_close(intdll); return interr; } libverto-0.3.1/src/module.h000066400000000000000000000063421343534721300156000ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* Determines if a symbol is present in a given module. * * @param modname The name of the module. * @param symbname The name of the symbol. * @return Non-zero if found, zero if not found. */ int module_symbol_is_present(const char *modname, const char *symbname); /* Finds the file for a given symbol. * * If filename is non-null, the name of the file will be stored. This must * be freed with free(). * * @param addr The address to resolve. * @param filename Where to store the name of the file. * @return 0 on error, non-zero on success. */ int module_get_filename_for_symbol(void *addr, char **filename); /* Closes a module. * * Does nothing if dll is NULL. * * @param dll The module to close. */ void module_close(void *dll); /* Loads a module and extracts the given symbol. * * This function loads the module specified by filename, but does not resolve * any of its symbol dependencies. Next is gets the symbol symbname and calls * shouldload(). If shouldload() returns non-zero, the module is reloaded * with full symbol resolution and stores the results in dll and symb. * * The job of shouldload() is to determine, based on the metadata in the * symbol fetched, if the module should be fully loaded. The shouldload() * callback MUST NOT attempt to call any functions in the module. This will * crash on WIN32. * * If an error occurs, an error string will be allocated and returned. If * allocation of this string fails, NULL will be returned. Since this is the * same as the non-error case, you should additionally check if dll or symb * is NULL. * * @param filename Path to the module * @param symbname Symbol name to load from the file and pass to shouldload() * @param shouldload Callback to determine whether to fullly load the module * @param misc Opaque pointer to pass to shouldload() * @param dll Where the module will be stored (can be NULL) * @param symb Where the symbol will be stored (can be NULL) * @return An error string. */ char * module_load(const char *filename, const char *symbname, int (*shouldload)(void *symb, void *misc, char **err), void *misc, void **dll, void **symb); libverto-0.3.1/src/verto-glib.c000066400000000000000000000216061343534721300163600ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #define VERTO_MODULE_TYPES typedef struct { GMainContext *context; GMainLoop *loop; } verto_mod_ctx; typedef GSource verto_mod_ev; #include /* While glib has signal support in >=2.29, it does not support many common signals (like USR*). Therefore, signal support is disabled until they support them (should be soonish) */ #if GLIB_MAJOR_VERSION >= 999 #if GLIB_MINOR_VERSION >= 29 #ifdef G_OS_UNIX /* Not supported on Windows */ #include #define HAS_SIGNAL VERTO_EV_TYPE_SIGNAL #endif #endif /* GLIB_MINOR_VERSION >= 29 */ #endif /* GLIB_MAJOR_VERSION >= 2 */ #ifndef HAS_SIGNAL #define HAS_SIGNAL 0 #endif #define VERTO_GLIB_SUPPORTED_TYPES (VERTO_EV_TYPE_IO \ | VERTO_EV_TYPE_TIMEOUT \ | VERTO_EV_TYPE_IDLE \ | HAS_SIGNAL \ | VERTO_EV_TYPE_CHILD) typedef gboolean (*GIOCallback)(gpointer data, GIOCondition condition); typedef struct GIOSource { GSource source; GPollFD fd; gboolean autoclose; } GIOSource; static gboolean prepare(GSource *source, gint *timeout) { (void) source; *timeout = -1; return FALSE; } static gboolean check(GSource *source) { GIOSource *src = (GIOSource*) source; return src->fd.revents & src->fd.events; } static gboolean dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { GIOSource *src = (GIOSource*) source; return ((GIOCallback) callback)(user_data, src->fd.revents); } static void finalize(GSource *source) { GIOSource *src = (GIOSource*) source; if (src->autoclose) close(src->fd.fd); } static GSourceFuncs funcs = { prepare, check, dispatch, finalize, NULL, NULL }; static void * glib_convert_(GMainContext *mc, GMainLoop *ml) { verto_mod_ctx *l = NULL; l = g_new0(verto_mod_ctx, 1); if (l) { if (mc) { /* Steal references */ l->context = mc; l->loop = ml ? ml : g_main_loop_new(l->context, FALSE); if (g_main_context_default() == mc) g_main_context_ref(mc); } else { l->context = g_main_context_ref(g_main_context_default()); l->loop = g_main_loop_new(l->context, FALSE); } } else { g_main_loop_unref(ml); g_main_context_unref(mc); } return l; } static verto_mod_ctx * glib_ctx_new(void) { return glib_convert_(g_main_context_new(), NULL); } static verto_mod_ctx * glib_ctx_default(void) { return glib_convert_(g_main_context_default(), NULL); } static void glib_ctx_free(verto_mod_ctx *ctx) { g_main_loop_unref(ctx->loop); g_main_context_unref(ctx->context); g_free(ctx); } static void glib_ctx_run(verto_mod_ctx *ctx) { g_main_loop_run(ctx->loop); } static void glib_ctx_run_once(verto_mod_ctx *ctx) { g_main_context_iteration(ctx->context, TRUE); } static gboolean break_callback(gpointer loop) { g_main_loop_quit(loop); return FALSE; } static void glib_ctx_break(verto_mod_ctx *ctx) { GSource *src = g_timeout_source_new(0); g_assert(src); g_source_set_callback(src, break_callback, ctx->loop, NULL); g_source_set_priority(src, G_PRIORITY_HIGH); g_assert(g_source_attach(src, ctx->context) != 0); g_source_unref(src); } static gboolean glib_callback(gpointer data) { gboolean persists = verto_get_flags(data) & VERTO_EV_FLAG_PERSIST; verto_fire(data); return persists; } static gboolean glib_callback_io(gpointer data, GIOCondition condition) { verto_ev_flag state = VERTO_EV_FLAG_NONE; if (condition & (G_IO_IN | G_IO_PRI)) state |= VERTO_EV_FLAG_IO_READ; if (condition & G_IO_OUT) state |= VERTO_EV_FLAG_IO_WRITE; if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) state |= VERTO_EV_FLAG_IO_ERROR; verto_set_fd_state(data, state); return glib_callback(data); } static void glib_callback_child(GPid pid, gint status, gpointer data) { (void) pid; verto_set_proc_status(data, status); verto_fire(data); } static void glib_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) { (void) ctx; if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_HIGH) g_source_set_priority(evpriv, G_PRIORITY_HIGH); else if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_MEDIUM) g_source_set_priority(evpriv, G_PRIORITY_DEFAULT_IDLE); else if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_LOW) g_source_set_priority(evpriv, G_PRIORITY_LOW); if (verto_get_type(ev) == VERTO_EV_TYPE_IO) { ((GIOSource*) evpriv)->fd.events = 0; if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) ((GIOSource*) evpriv)->fd.events |= G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL; if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) ((GIOSource*) evpriv)->fd.events |= G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL; } } static verto_mod_ev * glib_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) { verto_mod_ev *evpriv = NULL; verto_ev_type type = verto_get_type(ev); *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_PERSIST; *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_IO_CLOSE_FD; switch (type) { case VERTO_EV_TYPE_IO: evpriv = g_source_new(&funcs, sizeof(GIOSource)); if (evpriv) { ((GIOSource*) evpriv)->fd.fd = verto_get_fd(ev); ((GIOSource*) evpriv)->autoclose = *flags & VERTO_EV_FLAG_IO_CLOSE_FD; g_source_add_poll(evpriv, &((GIOSource*) evpriv)->fd); } break; case VERTO_EV_TYPE_TIMEOUT: evpriv = g_timeout_source_new(verto_get_interval(ev)); break; case VERTO_EV_TYPE_IDLE: evpriv = g_idle_source_new(); break; case VERTO_EV_TYPE_CHILD: evpriv = g_child_watch_source_new(verto_get_proc(ev)); break; case VERTO_EV_TYPE_SIGNAL: /* While glib has signal support in >=2.29, it does not support many common signals (like USR*). Therefore, signal support is disabled until they support them (should be soonish) */ #if GLIB_MAJOR_VERSION >= 999 #if GLIB_MINOR_VERSION >= 29 #ifdef G_OS_UNIX /* Not supported on Windows */ evpriv = g_unix_signal_source_new(verto_get_signal(ev)); break; #endif #endif /* GLIB_MINOR_VERSION >= 29 */ #endif /* GLIB_MAJOR_VERSION >= 2 */ default: return NULL; /* Not supported */ } if (!evpriv) goto error; if (type == VERTO_EV_TYPE_IO) g_source_set_callback(evpriv, (GSourceFunc) glib_callback_io, (void *) ev, NULL); else if (type == VERTO_EV_TYPE_CHILD) g_source_set_callback(evpriv, (GSourceFunc) glib_callback_child, (void *) ev, NULL); else g_source_set_callback(evpriv, glib_callback, (void *) ev, NULL); glib_ctx_set_flags(ctx, ev, evpriv); g_source_set_can_recurse(evpriv, FALSE); if (g_source_attach(evpriv, ctx->context) == 0) goto error; return evpriv; error: if (evpriv) { g_source_destroy(evpriv); g_source_unref(evpriv); } return NULL; } static void glib_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) { (void) ctx; if (!ev) return; g_source_destroy(evpriv); g_source_unref(evpriv); } #define glib_ctx_reinitialize NULL VERTO_MODULE(glib, g_main_context_default, VERTO_GLIB_SUPPORTED_TYPES); verto_ctx * verto_convert_glib(GMainContext *mc, GMainLoop *ml) { return verto_convert(glib, 0, glib_convert_(mc, ml)); } libverto-0.3.1/src/verto-glib.h000066400000000000000000000032131343534721300163570ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef VERTO_GLIB_H_ #define VERTO_GLIB_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ verto_ctx * verto_new_glib(void); verto_ctx * verto_default_glib(void); /** * mc == NULL, ml == NULL -- Use the default main loop * * If mc is specified, a reference is stolen unless mc is the default loop. * A reference is always stolen for ml. */ verto_ctx * verto_convert_glib(GMainContext *mc, GMainLoop *ml); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* VERTO_GLIB_H_ */ libverto-0.3.1/src/verto-libev.c000066400000000000000000000126621343534721300165460ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #define VERTO_MODULE_TYPES typedef struct ev_loop verto_mod_ctx; typedef ev_watcher verto_mod_ev; #include static verto_mod_ctx * libev_ctx_new(void) { return ev_loop_new(EVFLAG_AUTO); } static verto_mod_ctx * libev_ctx_default(void) { return ev_default_loop(EVFLAG_AUTO); } static void libev_ctx_free(verto_mod_ctx *ctx) { if (ctx != EV_DEFAULT) ev_loop_destroy(ctx); } static void libev_ctx_run(verto_mod_ctx *ctx) { ev_run(ctx, 0); } static void libev_ctx_run_once(verto_mod_ctx *ctx) { ev_run(ctx, EVRUN_ONCE); } static void libev_ctx_break(verto_mod_ctx *ctx) { ev_break(ctx, EVBREAK_ONE); } static void libev_ctx_reinitialize(verto_mod_ctx *ctx) { ev_loop_fork(ctx); } static void libev_callback(EV_P_ ev_watcher *w, int revents) { verto_ev_flag state = VERTO_EV_FLAG_NONE; #if EV_MULTIPLICITY /* Match the check in ev.h, which doesn't mark this unused */ (void) EV_A; #endif if (verto_get_type(w->data)== VERTO_EV_TYPE_CHILD) verto_set_proc_status(w->data, ((ev_child*) w)->rstatus); if (revents & EV_READ) state |= VERTO_EV_FLAG_IO_READ; if (revents & EV_WRITE) state |= VERTO_EV_FLAG_IO_WRITE; if (revents & EV_ERROR) state |= VERTO_EV_FLAG_IO_ERROR; verto_set_fd_state(w->data, state); verto_fire(w->data); } static void libev_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) { if (verto_get_type(ev) == VERTO_EV_TYPE_IO) { int events = EV_NONE; if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) events |= EV_READ; if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) events |= EV_WRITE; ev_io_stop(ctx, (ev_io*) evpriv); ev_io_set(((ev_io*) evpriv), verto_get_fd(ev), events); ev_io_start(ctx, (ev_io*) evpriv); } } #define setuptype(type, ...) \ w.type = malloc(sizeof(ev_ ## type)); \ if (w.type) { \ ev_ ## type ## _init(w.type, (EV_CB(type, (*))) __VA_ARGS__); \ ev_ ## type ## _start(ctx, w.type); \ } \ break static verto_mod_ev * libev_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) { union { ev_watcher *watcher; ev_io *io; ev_timer *timer; ev_idle *idle; ev_signal *signal; ev_child *child; } w; ev_tstamp interval; w.watcher = NULL; *flags |= VERTO_EV_FLAG_PERSIST; switch (verto_get_type(ev)) { case VERTO_EV_TYPE_IO: setuptype(io, libev_callback, verto_get_fd(ev), EV_NONE); case VERTO_EV_TYPE_TIMEOUT: interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0; setuptype(timer, libev_callback, interval, interval); case VERTO_EV_TYPE_IDLE: setuptype(idle, libev_callback); case VERTO_EV_TYPE_SIGNAL: setuptype(signal, libev_callback, verto_get_signal(ev)); case VERTO_EV_TYPE_CHILD: *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */ setuptype(child, libev_callback, verto_get_proc(ev), 0); default: break; /* Not supported */ } if (w.watcher) { w.watcher->data = (void*) ev; libev_ctx_set_flags(ctx, ev, w.watcher); } return w.watcher; } static void libev_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) { switch (verto_get_type(ev)) { case VERTO_EV_TYPE_IO: ev_io_stop(ctx, (ev_io*) evpriv); break; case VERTO_EV_TYPE_TIMEOUT: ev_timer_stop(ctx, (ev_timer*) evpriv); break; case VERTO_EV_TYPE_IDLE: ev_idle_stop(ctx, (ev_idle*) evpriv); break; case VERTO_EV_TYPE_SIGNAL: ev_signal_stop(ctx, (ev_signal*) evpriv); break; case VERTO_EV_TYPE_CHILD: ev_child_stop(ctx, (ev_child*) evpriv); break; default: break; } free(evpriv); } VERTO_MODULE(libev, ev_loop_new, VERTO_EV_TYPE_IO | VERTO_EV_TYPE_TIMEOUT | VERTO_EV_TYPE_IDLE | VERTO_EV_TYPE_SIGNAL | VERTO_EV_TYPE_CHILD); verto_ctx * verto_convert_libev(struct ev_loop* loop) { return verto_convert(libev, 0, loop); } libverto-0.3.1/src/verto-libev.h000066400000000000000000000027161343534721300165520ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef VERTO_LIBEV_H_ #define VERTO_LIBEV_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ verto_ctx * verto_new_libev(void); verto_ctx * verto_default_libev(void); verto_ctx * verto_convert_libev(struct ev_loop* loop); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* VERTO_LIBEV_H_ */ libverto-0.3.1/src/verto-libevent.c000066400000000000000000000120361343534721300172500ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #define VERTO_MODULE_TYPES typedef struct event_base verto_mod_ctx; typedef struct event verto_mod_ev; #include #include /* This is technically not exposed in any headers, but it is exported from * the binary. Without it, we can't provide compatibility with libevent's * sense of "global." */ extern struct event_base *event_global_current_base_; static verto_mod_ctx * libevent_ctx_new(void) { struct event_base *eb; eb = event_base_new(); event_base_priority_init(eb, 3); return eb; } static verto_mod_ctx * libevent_ctx_default(void) { if (!event_global_current_base_) event_global_current_base_ = event_init(); event_base_priority_init(event_global_current_base_, 3); return event_global_current_base_; } static void libevent_ctx_free(verto_mod_ctx *ctx) { event_base_free(ctx); } static void libevent_ctx_run(verto_mod_ctx *ctx) { event_base_dispatch(ctx); } static void libevent_ctx_run_once(verto_mod_ctx *ctx) { event_base_loop(ctx, EVLOOP_ONCE); } static void libevent_ctx_break(verto_mod_ctx *ctx) { event_base_loopbreak(ctx); } static void libevent_ctx_reinitialize(verto_mod_ctx *ctx) { event_reinit(ctx); } static void libevent_callback(evutil_socket_t socket, short type, void *data) { verto_ev_flag state = VERTO_EV_FLAG_NONE; (void) socket; if (type & EV_READ) state |= VERTO_EV_FLAG_IO_READ; if (type & EV_WRITE) state |= VERTO_EV_FLAG_IO_WRITE; #ifdef EV_ERROR if (type & EV_ERROR) state |= VERTO_EV_FLAG_IO_ERROR; #endif verto_set_fd_state(data, state); verto_fire(data); } static verto_mod_ev * libevent_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) { struct event *priv = NULL; struct timeval *timeout = NULL; struct timeval tv; int libeventflags = 0; *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_PERSIST; if (verto_get_flags(ev) & VERTO_EV_FLAG_PERSIST) libeventflags |= EV_PERSIST; switch (verto_get_type(ev)) { case VERTO_EV_TYPE_IO: if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) libeventflags |= EV_READ; if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) libeventflags |= EV_WRITE; priv = event_new(ctx, verto_get_fd(ev), libeventflags, libevent_callback, (void *) ev); break; case VERTO_EV_TYPE_TIMEOUT: timeout = &tv; tv.tv_sec = verto_get_interval(ev) / 1000; tv.tv_usec = verto_get_interval(ev) % 1000 * 1000; priv = event_new(ctx, -1, EV_TIMEOUT | libeventflags, libevent_callback, (void *) ev); break; case VERTO_EV_TYPE_SIGNAL: priv = event_new(ctx, verto_get_signal(ev), EV_SIGNAL | libeventflags, libevent_callback, (void *) ev); break; case VERTO_EV_TYPE_IDLE: case VERTO_EV_TYPE_CHILD: default: return NULL; /* Not supported */ } if (!priv) return NULL; if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_HIGH) event_priority_set(priv, 0); else if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_MEDIUM) event_priority_set(priv, 1); else if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_LOW) event_priority_set(priv, 2); event_add(priv, timeout); return priv; } static void libevent_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) { (void) ctx; (void) ev; event_del(evpriv); event_free(evpriv); } #define libevent_ctx_set_flags NULL VERTO_MODULE(libevent, event_base_init, VERTO_EV_TYPE_IO | VERTO_EV_TYPE_TIMEOUT | VERTO_EV_TYPE_SIGNAL); verto_ctx * verto_convert_libevent(struct event_base* base) { event_base_priority_init(base, 3); return verto_convert(libevent, 0, base); } libverto-0.3.1/src/verto-libevent.h000066400000000000000000000027561343534721300172650ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef VERTO_LIBEVENT_H_ #define VERTO_LIBEVENT_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ verto_ctx * verto_new_libevent(void); verto_ctx * verto_default_libevent(void); verto_ctx * verto_convert_libevent(struct event_base *ebase); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* VERTO_LIBEVENT_H_ */ libverto-0.3.1/src/verto-module.h000066400000000000000000000147601343534721300167400ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/ #ifndef VERTO_MODULE_H_ #define VERTO_MODULE_H_ #include #ifndef VERTO_MODULE_TYPES #define VERTO_MODULE_TYPES typedef void verto_mod_ctx; typedef void verto_mod_ev; #endif #define VERTO_MODULE_VERSION 3 #define VERTO_MODULE_TABLE(name) verto_module_table_ ## name #define VERTO_MODULE(name, symb, types) \ static verto_ctx_funcs name ## _funcs = { \ name ## _ctx_new, \ name ## _ctx_default, \ name ## _ctx_free, \ name ## _ctx_run, \ name ## _ctx_run_once, \ name ## _ctx_break, \ name ## _ctx_reinitialize, \ name ## _ctx_set_flags, \ name ## _ctx_add, \ name ## _ctx_del \ }; \ verto_module VERTO_MODULE_TABLE(name) = { \ VERTO_MODULE_VERSION, \ # name, \ # symb, \ types, \ &name ## _funcs, \ }; \ verto_ctx * \ verto_new_ ## name() \ { \ return verto_convert(name, 0, NULL); \ } \ verto_ctx * \ verto_default_ ## name() \ { \ return verto_convert(name, 1, NULL); \ } typedef struct { /* Required */ verto_mod_ctx *(*ctx_new)(); /* Optional */ verto_mod_ctx *(*ctx_default)(); /* Required */ void (*ctx_free)(verto_mod_ctx *ctx); /* Optional */ void (*ctx_run)(verto_mod_ctx *ctx); /* Required */ void (*ctx_run_once)(verto_mod_ctx *ctx); /* Optional */ void (*ctx_break)(verto_mod_ctx *ctx); /* Optional */ void (*ctx_reinitialize)(verto_mod_ctx *ctx); /* Optional */ void (*ctx_set_flags)(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *modev); /* Required */ verto_mod_ev *(*ctx_add)(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags); /* Required */ void (*ctx_del)(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *modev); } verto_ctx_funcs; typedef struct { unsigned int vers; const char *name; const char *symb; verto_ev_type types; verto_ctx_funcs *funcs; } verto_module; /** * Converts an existing implementation specific loop to a verto_ctx. * * This function also sets the internal default implementation so that future * calls to verto_new(NULL) or verto_default(NULL) will use this specific * implementation if it was not already set. * * @param name The name of the module (unquoted) * @param deflt Whether the ctx is the default context or not * @param ctx The context to store * @return A new verto_ctx, or NULL on error. Call verto_free() when done. */ #define verto_convert(name, deflt, ctx) \ verto_convert_module(&VERTO_MODULE_TABLE(name), deflt, ctx) /** * Converts an existing implementation specific loop to a verto_ctx. * * If you are a module implementation, you probably want the macro above. This * function is generally used directly only when an application is attempting * to expose a home-grown event loop to verto. * * If deflt is non-zero and a default ctx was already defined for this module * and ctx is not NULL, than ctx will be free'd and the previously defined * default will be returned. * * If ctx is non-NULL, than the pre-existing verto_mod_ctx will be converted to * to a verto_ctx; if deflt is non-zero than this verto_mod_ctx will also be * marked as the default loop for this process. If ctx is NULL, than the * appropriate constructor will be called: either module->ctx_new() or * module->ctx_default() depending on the boolean value of deflt. If * module->ctx_default is NULL and deflt is non-zero, than module->ctx_new() * will be called and the resulting verto_mod_ctx will be utilized as the * default. * * This function also sets the internal default implementation so that future * calls to verto_new(NULL) or verto_default(NULL) will use this specific * implementation if it was not already set. * * @param name The name of the module (unquoted) * @param ctx The context private to store * @return A new verto_ctx, or NULL on error. Call verto_free() when done. */ verto_ctx * verto_convert_module(const verto_module *module, int deflt, verto_mod_ctx *ctx); /** * Calls the callback of the verto_ev and then frees it via verto_del(). * * The verto_ev is not freed (verto_del() is not called) if it is a signal event. * * @see verto_add_read() * @see verto_add_write() * @see verto_add_timeout() * @see verto_add_idle() * @see verto_add_signal() * @see verto_add_child() * @see verto_del() * @param ev The verto_ev */ void verto_fire(verto_ev *ev); /** * Sets the status of the pid/handle which caused this event to fire. * * This function does nothing if the verto_ev is not a child type. * * @see verto_add_child() * @param ev The verto_ev to set the status in. * @param status The pid/handle status. */ void verto_set_proc_status(verto_ev *ev, verto_proc_status status); /** * Sets the state of the fd which caused this event to fire. * * This function does nothing if the verto_ev is not a io type. * * Only the flags VERTO_EV_FLAG_IO_(READ|WRITE|ERROR) are supported. All other * flags are unset. * * @see verto_add_io() * @param ev The verto_ev to set the state in. * @param state The fd state. */ void verto_set_fd_state(verto_ev *ev, verto_ev_flag state); #endif /* VERTO_MODULE_H_ */ libverto-0.3.1/src/verto-tevent.c000066400000000000000000000112511343534721300167430ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #define VERTO_MODULE_TYPES typedef struct tevent_context verto_mod_ctx; typedef void verto_mod_ev; #include #ifndef TEVENT_FD_ERROR #define TEVENT_FD_ERROR 0 #endif /* TEVENT_FD_ERROR */ static verto_mod_ctx * tevent_ctx_new(void) { return tevent_context_init(NULL); } static void tevent_ctx_free(verto_mod_ctx *ctx) { talloc_free(ctx); } static void tevent_ctx_run_once(verto_mod_ctx *ctx) { tevent_loop_once(ctx); } static void tevent_ctx_reinitialize(verto_mod_ctx *ctx) { tevent_re_initialise(ctx); } static void tevent_fd_cb(struct tevent_context *c, struct tevent_fd *e, uint16_t fl, void *data) { verto_ev_flag state = VERTO_EV_FLAG_NONE; if (fl & TEVENT_FD_READ) state |= VERTO_EV_FLAG_IO_READ; if (fl & TEVENT_FD_WRITE) state |= VERTO_EV_FLAG_IO_WRITE; if (fl & TEVENT_FD_ERROR) state |= VERTO_EV_FLAG_IO_ERROR; verto_set_fd_state(data, state); verto_fire(data); } static void tevent_timer_cb(struct tevent_context *c, struct tevent_timer *e, struct timeval ct, void *data) { verto_fire(data); } static void tevent_signal_cb(struct tevent_context *c, struct tevent_signal *e, int signum, int count, void *siginfo, void *data) { verto_fire(data); } static void tevent_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) { if (verto_get_type(ev) == VERTO_EV_TYPE_IO) { uint16_t teventflags = TEVENT_FD_ERROR; if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) teventflags |= TEVENT_FD_READ; if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) teventflags |= TEVENT_FD_WRITE; tevent_fd_set_flags(evpriv, teventflags); } } static verto_mod_ev * tevent_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) { time_t interval; struct timeval tv; struct tevent_fd *tfde; *flags |= VERTO_EV_FLAG_PERSIST; switch (verto_get_type(ev)) { case VERTO_EV_TYPE_IO: tfde = tevent_add_fd(ctx, ctx, verto_get_fd(ev), TEVENT_FD_ERROR, tevent_fd_cb, (void *) ev); if (tfde) { tevent_ctx_set_flags(ctx, ev, tfde); if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_CLOSE_FD) { *flags |= VERTO_EV_FLAG_IO_CLOSE_FD; tevent_fd_set_auto_close(tfde); } } return tfde; case VERTO_EV_TYPE_TIMEOUT: *flags &= ~VERTO_EV_FLAG_PERSIST; /* Timeout events don't persist */ interval = verto_get_interval(ev); tv = tevent_timeval_current_ofs(interval / 1000, interval % 1000 * 1000); return tevent_add_timer(ctx, ctx, tv, tevent_timer_cb, (void *) ev); case VERTO_EV_TYPE_SIGNAL: return tevent_add_signal(ctx, ctx, verto_get_signal(ev), 0, tevent_signal_cb, (void *) ev); case VERTO_EV_TYPE_IDLE: case VERTO_EV_TYPE_CHILD: default: return NULL; /* Not supported */ } } static void tevent_ctx_del(verto_mod_ctx *priv, const verto_ev *ev, verto_mod_ev *evpriv) { talloc_free(evpriv); } #define tevent_ctx_break NULL #define tevent_ctx_run NULL #define tevent_ctx_default NULL VERTO_MODULE(tevent, tevent_context_init, VERTO_EV_TYPE_IO | VERTO_EV_TYPE_TIMEOUT | VERTO_EV_TYPE_SIGNAL); verto_ctx * verto_convert_tevent(struct tevent_context *context) { return verto_convert(tevent, 0, context); } libverto-0.3.1/src/verto-tevent.h000066400000000000000000000027421343534721300167550ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef VERTO_TEVENT_H_ #define VERTO_TEVENT_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ verto_ctx * verto_new_tevent(void); verto_ctx * verto_default_tevent(void); verto_ctx * verto_convert_tevent(struct tevent_context *context); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* VERTO_TEVENT_H_ */ libverto-0.3.1/src/verto.c000066400000000000000000000624171343534721300154520ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_PTHREAD #include #endif #include #include "module.h" #define _str(s) # s #define __str(s) _str(s) #define MUTABLE(flags) (flags & _VERTO_EV_FLAG_MUTABLE_MASK) /* Remove flags we can emulate */ #define make_actual(flags) ((flags) & ~(VERTO_EV_FLAG_PERSIST|VERTO_EV_FLAG_IO_CLOSE_FD)) struct verto_ctx { size_t ref; verto_mod_ctx *ctx; const verto_module *module; verto_ev *events; int deflt; int exit; }; typedef struct { verto_proc proc; verto_proc_status status; } verto_child; typedef struct { int fd; verto_ev_flag state; } verto_io; struct verto_ev { verto_ev *next; verto_ctx *ctx; verto_ev_type type; verto_callback *callback; verto_callback *onfree; void *priv; verto_mod_ev *ev; verto_ev_flag flags; verto_ev_flag actual; size_t depth; int deleted; union { verto_io io; int signal; time_t interval; verto_child child; } option; }; typedef struct module_record module_record; struct module_record { module_record *next; const verto_module *module; void *dll; char *filename; verto_ctx *defctx; }; #ifdef BUILTIN_MODULE #define _MODTABLE(n) verto_module_table_ ## n #define MODTABLE(n) _MODTABLE(n) /* * This symbol can be used when embedding verto.c in a library along with a * built-in private module, to preload the module instead of dynamically * linking it in later. Define to . */ extern verto_module MODTABLE(BUILTIN_MODULE); static module_record builtin_record = { NULL, &MODTABLE(BUILTIN_MODULE), NULL, "", NULL }; static module_record *loaded_modules = &builtin_record; #else static module_record *loaded_modules; #endif static void *(*resize_cb)(void *mem, size_t size); static int resize_cb_hierarchical; #ifdef HAVE_PTHREAD static pthread_mutex_t loaded_modules_mutex = PTHREAD_MUTEX_INITIALIZER; #ifndef NDEBUG #define mutex_lock(x) { \ int c = pthread_mutex_lock(x); \ if (c != 0) { \ fprintf(stderr, "pthread_mutex_lock returned %d (%s) in %s", \ c, strerror(c), __FUNCTION__); \ } \ assert(c == 0); \ } #define mutex_unlock(x) { \ int c = pthread_mutex_unlock(x); \ if (c != 0) { \ fprintf(stderr, "pthread_mutex_unlock returned %d (%s) in %s", \ c, strerror(c), __FUNCTION__); \ } \ assert(c == 0); \ } #define mutex_destroy(x) { \ int c = pthread_mutex_destroy(x); \ if (c != 0) { \ fprintf(stderr, "pthread_mutex_destroy returned %d (%s) in %s", \ c, strerror(c), __FUNCTION__); \ } \ assert(c == 0); \ } #else /* NDEBUG */ #define mutex_lock pthread_mutex_lock #define mutex_unlock pthread_mutex_unlock #define mutex_destroy pthread_mutex_destroy #endif /* NDEBUG */ #else /* HAVE_PTHREAD */ #define mutex_lock(x) #define mutex_unlock(x) #define mutex_destroy(x) #endif /* HAVE_PTHREAD */ #define vfree(mem) vresize(mem, 0) static void * vresize(void *mem, size_t size) { if (!resize_cb) resize_cb = &realloc; if (size == 0 && resize_cb == &realloc) { /* Avoid memleak as realloc(X, 0) can return a free-able pointer. */ free(mem); return NULL; } return (*resize_cb)(mem, size); } #ifndef BUILTIN_MODULE static char * string_aconcat(const char *first, const char *second, const char *third) { char *ret; size_t len; len = strlen(first) + strlen(second); if (third) len += strlen(third); ret = malloc(len + 1); if (!ret) return NULL; strncpy(ret, first, strlen(first)); strncpy(ret + strlen(first), second, strlen(second)); if (third) strncpy(ret + strlen(first) + strlen(second), third, strlen(third)); ret[len] = '\0'; return ret; } static char * int_get_table_name_from_filename(const char *filename) { char *bn = NULL, *tmp = NULL; if (!filename) return NULL; tmp = strdup(filename); if (!tmp) return NULL; bn = basename(tmp); if (bn) bn = strdup(bn); free(tmp); if (!bn) return NULL; tmp = strchr(bn, '-'); if (tmp) { if (strchr(tmp+1, '.')) { *strchr(tmp+1, '.') = '\0'; tmp = string_aconcat(__str(VERTO_MODULE_TABLE()), tmp + 1, NULL); } else tmp = NULL; } free(bn); return tmp; } typedef struct { int reqsym; verto_ev_type reqtypes; } shouldload_data; static int shouldload(void *symb, void *misc, char **err) { verto_module *table = (verto_module*) symb; shouldload_data *data = (shouldload_data*) misc; /* Make sure we have the proper version */ if (table->vers != VERTO_MODULE_VERSION) { if (err) *err = strdup("Invalid module version!"); return 0; } /* Check to make sure that we have our required symbol if reqsym == true */ if (table->symb && data->reqsym && !module_symbol_is_present(NULL, table->symb)) { if (err) *err = string_aconcat("Symbol not found: ", table->symb, "!"); return 0; } /* Check to make sure that this module supports our required features */ if (data->reqtypes != VERTO_EV_TYPE_NONE && (table->types & data->reqtypes) != data->reqtypes) { if (err) *err = strdup("Module does not support required features!"); return 0; } return 1; } static int do_load_file(const char *filename, int reqsym, verto_ev_type reqtypes, module_record **record) { char *tblname = NULL, *error = NULL; module_record *tmp; shouldload_data data = { reqsym, reqtypes }; /* Check the loaded modules to see if we already loaded one */ mutex_lock(&loaded_modules_mutex); for (*record = loaded_modules ; *record ; *record = (*record)->next) { if (!strcmp((*record)->filename, filename)) { mutex_unlock(&loaded_modules_mutex); return 1; } } mutex_unlock(&loaded_modules_mutex); /* Create our module record */ tmp = *record = vresize(NULL, sizeof(module_record)); if (!tmp) return 0; memset(tmp, 0, sizeof(module_record)); tmp->filename = strdup(filename); if (!tmp->filename) { vfree(tmp); return 0; } /* Get the name of the module struct in the library */ tblname = int_get_table_name_from_filename(filename); if (!tblname) { free(tblname); free(tmp->filename); vfree(tmp); return 0; } /* Load the module */ error = module_load(filename, tblname, shouldload, &data, &tmp->dll, (void **) &tmp->module); if (error || !tmp->dll || !tmp->module) { /*if (error) fprintf(stderr, "%s\n", error);*/ free(error); module_close(tmp->dll); free(tblname); free(tmp->filename); vfree(tmp); return 0; } /* Append the new module to the end of the loaded modules */ mutex_lock(&loaded_modules_mutex); for (tmp = loaded_modules ; tmp && tmp->next; tmp = tmp->next) continue; if (tmp) tmp->next = *record; else loaded_modules = *record; mutex_unlock(&loaded_modules_mutex); free(tblname); return 1; } static int do_load_dir(const char *dirname, const char *prefix, const char *suffix, int reqsym, verto_ev_type reqtypes, module_record **record) { DIR *dir; struct dirent *ent = NULL; *record = NULL; dir = opendir(dirname); if (!dir) return 0; while ((ent = readdir(dir))) { char *tmp = NULL; int success; size_t flen, slen; flen = strlen(ent->d_name); slen = strlen(suffix); if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name)) continue; if (strstr(ent->d_name, prefix) != ent->d_name) continue; if (flen < slen || strcmp(ent->d_name + flen - slen, suffix)) continue; tmp = string_aconcat(dirname, "/", ent->d_name); if (!tmp) continue; success = do_load_file(tmp, reqsym, reqtypes, record); free(tmp); if (success) break; *record = NULL; } closedir(dir); return *record != NULL; } #endif static int load_module(const char *impl, verto_ev_type reqtypes, module_record **record) { int success = 0; #ifndef BUILTIN_MODULE char *prefix = NULL; char *suffix = NULL; char *tmp = NULL; #endif /* Check the cache */ mutex_lock(&loaded_modules_mutex); if (impl) { for (*record = loaded_modules ; *record ; *record = (*record)->next) { if ((strchr(impl, '/') && !strcmp(impl, (*record)->filename)) || !strcmp(impl, (*record)->module->name)) { mutex_unlock(&loaded_modules_mutex); return 1; } } } else if (loaded_modules) { for (*record = loaded_modules ; *record ; *record = (*record)->next) { if (reqtypes == VERTO_EV_TYPE_NONE || ((*record)->module->types & reqtypes) == reqtypes) { mutex_unlock(&loaded_modules_mutex); return 1; } } } mutex_unlock(&loaded_modules_mutex); #ifndef BUILTIN_MODULE if (!module_get_filename_for_symbol(verto_convert_module, &prefix)) return 0; /* Example output: * prefix == /usr/lib/libverto- * impl == glib * suffix == .so.0 * Put them all together: /usr/lib/libverto-glib.so.0 */ tmp = strdup(prefix); if (!tmp) { free(prefix); return 0; } suffix = basename(tmp); suffix = strchr(suffix, '.'); if (!suffix || strlen(suffix) < 1 || !(suffix = strdup(suffix))) { free(prefix); free(tmp); return 0; } strcpy(prefix + strlen(prefix) - strlen(suffix), "-"); free(tmp); if (impl) { /* Try to do a load by the path */ if (!success && strchr(impl, '/')) success = do_load_file(impl, 0, reqtypes, record); if (!success) { /* Try to do a load by the name */ tmp = string_aconcat(prefix, impl, suffix); if (tmp) { success = do_load_file(tmp, 0, reqtypes, record); free(tmp); } } } else { /* NULL was passed, so we will use the dirname of * the prefix to try and find any possible plugins */ tmp = strdup(prefix); if (tmp) { char *dname = strdup(dirname(tmp)); free(tmp); tmp = strdup(basename(prefix)); free(prefix); prefix = tmp; if (dname && prefix) { /* Attempt to find a module we are already linked to */ success = do_load_dir(dname, prefix, suffix, 1, reqtypes, record); if (!success) { #ifdef DEFAULT_MODULE /* Attempt to find the default module */ success = load_module(DEFAULT_MODULE, reqtypes, record); if (!success) #endif /* DEFAULT_MODULE */ /* Attempt to load any plugin (we're desperate) */ success = do_load_dir(dname, prefix, suffix, 0, reqtypes, record); } } free(dname); } } free(suffix); free(prefix); #endif /* BUILTIN_MODULE */ return success; } static verto_ev * make_ev(verto_ctx *ctx, verto_callback *callback, verto_ev_type type, verto_ev_flag flags) { verto_ev *ev = NULL; if (!ctx || !callback) return NULL; ev = vresize(NULL, sizeof(verto_ev)); if (ev) { memset(ev, 0, sizeof(verto_ev)); ev->ctx = ctx; ev->type = type; ev->callback = callback; ev->flags = flags; } return ev; } static void push_ev(verto_ctx *ctx, verto_ev *ev) { verto_ev *tmp; if (!ctx || !ev) return; tmp = ctx->events; ctx->events = ev; ctx->events->next = tmp; } static void remove_ev(verto_ev **origin, verto_ev *item) { if (!origin || !*origin || !item) return; if (*origin == item) *origin = (*origin)->next; else remove_ev(&((*origin)->next), item); } static void signal_ignore(verto_ctx *ctx, verto_ev *ev) { (void) ctx; (void) ev; } verto_ctx * verto_new(const char *impl, verto_ev_type reqtypes) { module_record *mr = NULL; if (!load_module(impl, reqtypes, &mr)) return NULL; return verto_convert_module(mr->module, 0, NULL); } verto_ctx * verto_default(const char *impl, verto_ev_type reqtypes) { module_record *mr = NULL; if (!load_module(impl, reqtypes, &mr)) return NULL; return verto_convert_module(mr->module, 1, NULL); } int verto_set_default(const char *impl, verto_ev_type reqtypes) { module_record *mr; mutex_lock(&loaded_modules_mutex); if (loaded_modules || !impl) { mutex_unlock(&loaded_modules_mutex); return 0; } mutex_unlock(&loaded_modules_mutex); return load_module(impl, reqtypes, &mr); } int verto_set_allocator(void *(*resize)(void *mem, size_t size), int hierarchical) { if (resize_cb || !resize) return 0; resize_cb = resize; resize_cb_hierarchical = hierarchical; return 1; } void verto_free(verto_ctx *ctx) { if (!ctx) return; ctx->ref = ctx->ref > 0 ? ctx->ref - 1 : 0; if (ctx->ref > 0) return; /* Cancel all pending events */ while (ctx->events) verto_del(ctx->events); /* Free the private */ if (!ctx->deflt || !ctx->module->funcs->ctx_default) ctx->module->funcs->ctx_free(ctx->ctx); vfree(ctx); } void verto_cleanup(void) { module_record *record; mutex_lock(&loaded_modules_mutex); for (record = loaded_modules; record; record = record->next) { module_close(record->dll); free(record->filename); } vfree(loaded_modules); loaded_modules = NULL; mutex_unlock(&loaded_modules_mutex); mutex_destroy(&loaded_modules_mutex); } void verto_run(verto_ctx *ctx) { if (!ctx) return; if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run) ctx->module->funcs->ctx_run(ctx->ctx); else { while (!ctx->exit) ctx->module->funcs->ctx_run_once(ctx->ctx); ctx->exit = 0; } } void verto_run_once(verto_ctx *ctx) { if (!ctx) return; ctx->module->funcs->ctx_run_once(ctx->ctx); } void verto_break(verto_ctx *ctx) { if (!ctx) return; if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run) ctx->module->funcs->ctx_break(ctx->ctx); else ctx->exit = 1; } int verto_reinitialize(verto_ctx *ctx) { verto_ev *tmp, *next; int error = 1; if (!ctx) return 0; /* Delete all events, but keep around the forkable ev structs */ for (tmp = ctx->events; tmp; tmp = next) { next = tmp->next; if (tmp->flags & VERTO_EV_FLAG_REINITIABLE) ctx->module->funcs->ctx_del(ctx->ctx, tmp, tmp->ev); else verto_del(tmp); } /* Reinit the loop */ if (ctx->module->funcs->ctx_reinitialize) ctx->module->funcs->ctx_reinitialize(ctx->ctx); /* Recreate events that were marked forkable */ for (tmp = ctx->events; tmp; tmp = tmp->next) { tmp->actual = make_actual(tmp->flags); tmp->ev = ctx->module->funcs->ctx_add(ctx->ctx, tmp, &tmp->actual); if (!tmp->ev) error = 0; } return error; } #define doadd(ev, set, type) \ ev = make_ev(ctx, callback, type, flags); \ if (ev) { \ set; \ ev->actual = make_actual(ev->flags); \ ev->ev = ctx->module->funcs->ctx_add(ctx->ctx, ev, &ev->actual); \ if (!ev->ev) { \ vfree(ev); \ return NULL; \ } \ push_ev(ctx, ev); \ } verto_ev * verto_add_io(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, int fd) { verto_ev *ev; if (fd < 0 || !(flags & (VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE))) return NULL; doadd(ev, ev->option.io.fd = fd, VERTO_EV_TYPE_IO); return ev; } verto_ev * verto_add_timeout(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, time_t interval) { verto_ev *ev; doadd(ev, ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT); return ev; } verto_ev * verto_add_idle(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback) { verto_ev *ev; doadd(ev,, VERTO_EV_TYPE_IDLE); return ev; } verto_ev * verto_add_signal(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, int signal) { verto_ev *ev; if (signal < 0) return NULL; #ifndef WIN32 if (signal == SIGCHLD) return NULL; #endif if (callback == VERTO_SIG_IGN) { callback = signal_ignore; if (!(flags & VERTO_EV_FLAG_PERSIST)) return NULL; } doadd(ev, ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL); return ev; } verto_ev * verto_add_child(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, verto_proc proc) { verto_ev *ev; if (flags & VERTO_EV_FLAG_PERSIST) /* persist makes no sense */ return NULL; #ifdef WIN32 if (proc == NULL) #else if (proc < 1) #endif return NULL; doadd(ev, ev->option.child.proc = proc, VERTO_EV_TYPE_CHILD); return ev; } void verto_set_private(verto_ev *ev, void *priv, verto_callback *free) { if (!ev) return; if (ev->onfree && free) ev->onfree(ev->ctx, ev); ev->priv = priv; ev->onfree = free; } void * verto_get_private(const verto_ev *ev) { return ev->priv; } verto_ev_type verto_get_type(const verto_ev *ev) { return ev->type; } verto_ev_flag verto_get_flags(const verto_ev *ev) { return ev->flags; } void verto_set_flags(verto_ev *ev, verto_ev_flag flags) { if (!ev) return; /* No modification is needed, so do nothing. */ if (MUTABLE(ev->flags) == MUTABLE(flags)) return; ev->flags &= ~_VERTO_EV_FLAG_MUTABLE_MASK; ev->flags |= MUTABLE(flags); /* If setting flags isn't supported, just rebuild the event */ if (!ev->ctx->module->funcs->ctx_set_flags) { ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev); ev->actual = make_actual(ev->flags); ev->ev = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual); assert(ev->ev); /* Here is the main reason why modules should */ return; /* implement set_flags(): we cannot fail gracefully. */ } ev->actual &= ~_VERTO_EV_FLAG_MUTABLE_MASK; ev->actual |= MUTABLE(flags); ev->ctx->module->funcs->ctx_set_flags(ev->ctx->ctx, ev, ev->ev); } int verto_get_fd(const verto_ev *ev) { if (ev && (ev->type == VERTO_EV_TYPE_IO)) return ev->option.io.fd; return -1; } verto_ev_flag verto_get_fd_state(const verto_ev *ev) { return ev->option.io.state; } time_t verto_get_interval(const verto_ev *ev) { if (ev && (ev->type == VERTO_EV_TYPE_TIMEOUT)) return ev->option.interval; return 0; } int verto_get_signal(const verto_ev *ev) { if (ev && (ev->type == VERTO_EV_TYPE_SIGNAL)) return ev->option.signal; return -1; } verto_proc verto_get_proc(const verto_ev *ev) { if (ev && ev->type == VERTO_EV_TYPE_CHILD) return ev->option.child.proc; return (verto_proc) 0; } verto_proc_status verto_get_proc_status(const verto_ev *ev) { return ev->option.child.status; } verto_ctx * verto_get_ctx(const verto_ev *ev) { return ev->ctx; } void verto_del(verto_ev *ev) { if (!ev) return; /* If the event is freed in the callback, we just set a flag so that * verto_fire() can actually do the delete when the callback completes. * * If we don't do this, than verto_fire() will access freed memory. */ if (ev->depth > 0) { ev->deleted = 1; return; } if (ev->onfree) ev->onfree(ev->ctx, ev); ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev); remove_ev(&(ev->ctx->events), ev); if ((ev->type == VERTO_EV_TYPE_IO) && (ev->flags & VERTO_EV_FLAG_IO_CLOSE_FD) && !(ev->actual & VERTO_EV_FLAG_IO_CLOSE_FD)) close(ev->option.io.fd); vfree(ev); } verto_ev_type verto_get_supported_types(verto_ctx *ctx) { return ctx->module->types; } /*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/ verto_ctx * verto_convert_module(const verto_module *module, int deflt, verto_mod_ctx *mctx) { verto_ctx *ctx = NULL; module_record *mr; if (!module) return NULL; if (deflt) { mutex_lock(&loaded_modules_mutex); for (mr = loaded_modules ; mr ; mr = mr->next) { verto_ctx *tmp; if (mr->module == module && mr->defctx) { if (mctx) module->funcs->ctx_free(mctx); tmp = mr->defctx; tmp->ref++; mutex_unlock(&loaded_modules_mutex); return tmp; } } mutex_unlock(&loaded_modules_mutex); } if (!mctx) { mctx = deflt ? (module->funcs->ctx_default ? module->funcs->ctx_default() : module->funcs->ctx_new()) : module->funcs->ctx_new(); if (!mctx) goto error; } ctx = vresize(NULL, sizeof(verto_ctx)); if (!ctx) goto error; memset(ctx, 0, sizeof(verto_ctx)); ctx->ref = 1; ctx->ctx = mctx; ctx->module = module; ctx->deflt = deflt; if (deflt) { module_record **tmp; mutex_lock(&loaded_modules_mutex); tmp = &loaded_modules; for (mr = loaded_modules ; mr ; mr = mr->next) { if (mr->module == module) { assert(mr->defctx == NULL); mr->defctx = ctx; mutex_unlock(&loaded_modules_mutex); return ctx; } if (!mr->next) { tmp = &mr->next; break; } } mutex_unlock(&loaded_modules_mutex); *tmp = vresize(NULL, sizeof(module_record)); if (!*tmp) { vfree(ctx); goto error; } memset(*tmp, 0, sizeof(module_record)); (*tmp)->defctx = ctx; (*tmp)->module = module; } return ctx; error: if (mctx) module->funcs->ctx_free(mctx); return NULL; } void verto_fire(verto_ev *ev) { void *priv; ev->depth++; ev->callback(ev->ctx, ev); ev->depth--; if (ev->depth == 0) { if (!(ev->flags & VERTO_EV_FLAG_PERSIST) || ev->deleted) verto_del(ev); else { if (!(ev->actual & VERTO_EV_FLAG_PERSIST)) { ev->actual = make_actual(ev->flags); priv = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual); assert(priv); /* TODO: create an error callback */ ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev); ev->ev = priv; } if (ev->type == VERTO_EV_TYPE_IO) ev->option.io.state = VERTO_EV_FLAG_NONE; if (ev->type == VERTO_EV_TYPE_CHILD) ev->option.child.status = 0; } } } void verto_set_proc_status(verto_ev *ev, verto_proc_status status) { if (ev && ev->type == VERTO_EV_TYPE_CHILD) ev->option.child.status = status; } void verto_set_fd_state(verto_ev *ev, verto_ev_flag state) { /* Filter out only the io flags */ state = state & (VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE | VERTO_EV_FLAG_IO_ERROR); /* Don't report read/write if the socket is closed */ if (state & VERTO_EV_FLAG_IO_ERROR) state = VERTO_EV_FLAG_IO_ERROR; if (ev && ev->type == VERTO_EV_TYPE_IO) ev->option.io.state = state; } libverto-0.3.1/src/verto.h000066400000000000000000000457551343534721300154650ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef VERTO_H_ #define VERTO_H_ #include /* For time_t */ #include /* For pid_t */ #ifdef WIN32 #include typedef HANDLE verto_proc; typedef DWORD verto_proc_status; #else #include typedef pid_t verto_proc; typedef int verto_proc_status; #endif #define VERTO_SIG_IGN ((verto_callback *) 1) #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef struct verto_ctx verto_ctx; typedef struct verto_ev verto_ev; typedef enum { VERTO_EV_TYPE_NONE = 0, VERTO_EV_TYPE_IO = 1, VERTO_EV_TYPE_TIMEOUT = 1 << 1, VERTO_EV_TYPE_IDLE = 1 << 2, VERTO_EV_TYPE_SIGNAL = 1 << 3, VERTO_EV_TYPE_CHILD = 1 << 4 } verto_ev_type; typedef enum { VERTO_EV_FLAG_NONE = 0, VERTO_EV_FLAG_PERSIST = 1, VERTO_EV_FLAG_PRIORITY_LOW = 1 << 1, VERTO_EV_FLAG_PRIORITY_MEDIUM = 1 << 2, VERTO_EV_FLAG_PRIORITY_HIGH = 1 << 3, VERTO_EV_FLAG_IO_READ = 1 << 4, VERTO_EV_FLAG_IO_WRITE = 1 << 5, VERTO_EV_FLAG_IO_ERROR = 1 << 7, VERTO_EV_FLAG_IO_CLOSE_FD = 1 << 8, VERTO_EV_FLAG_REINITIABLE = 1 << 6, _VERTO_EV_FLAG_MUTABLE_MASK = VERTO_EV_FLAG_PRIORITY_LOW | VERTO_EV_FLAG_PRIORITY_MEDIUM | VERTO_EV_FLAG_PRIORITY_HIGH | VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE, _VERTO_EV_FLAG_MAX = VERTO_EV_FLAG_IO_CLOSE_FD } verto_ev_flag; typedef void (verto_callback)(verto_ctx *ctx, verto_ev *ev); /** * Creates a new event context using an optionally specified implementation * and/or optionally specified required features. * * If you are an application that has already decided on using a particular * event loop implementation, you should not call this function, but instead * import the verto-NAME.h header and link against the verto-NAME.so, where * NAME is the implementation you wish to use. * * If you are a library, you should generally avoid creating event contexts * on your own but allow applications to pass in a verto_ctx you can use. * * There are two cases where you should use this function. The first is * where you have a need to choose an implementation at run time, usually * for testing purposes. The second and more common is when you simply * wish to remain implementation agnostic. In this later case, you should * always call like this: verto_new(NULL, ...). This lets verto choose the best * implementation to use. * * If impl is not NULL, a new context is returned which is backed by the * implementation specified. If the implementation specified is not * available or if the required types (reqtypes) are not provided by the * named implementation, NULL is returned. The parameter 'impl' can specify: * * The full path to an implementation library * * The name of the implementation library (i.e. - "glib" or "libev") * * If impl is NULL, verto will attempt to automatically determine the * best implementation to use. * * First, verto will attempt to use an existing, previously loaded * implementation. This is handled automatically by internal caching of either * the first implementation loaded or the one specified by verto_set_default(). * * Second, verto will attempt to discern if you are already linked to any * of the supported implementations (to avoid wasting memory by loading * extra unnecessary libraries). If you are linked to one supported * implementation, that implementation will be chosen. If you are linked * to more than one supported implementation one of the ones linked to * will be chosen, but the order of the particular choice is undefined. * * Third, verto will attempt to load the compile-time default, if defined at * build time and available at runtime. * * Last, verto will attempt to load any implementation installed. The specific * order of this step is undefined. * * In all cases above, if the implementation does not support all the specified * features (reqtypes), it will be skipped and processing will continue from * where it left off. This means that if verto_new() returns non-NULL it is * guaranteed to support the features you specified. * * @see verto_set_default() * @param impl The implementation to use, or NULL. * @param reqtypes A bitwise or'd list of required event type features. * @return A new verto_ctx, or NULL on error. Call verto_free() when done. */ verto_ctx * verto_new(const char *impl, verto_ev_type reqtypes); /** * Gets the default event context using an optionally specified implementation. * * This function is essentially a singleton version of verto_new(). However, * since this function must return the same loop as the *_default() call of * the underlying implementation (if such a function exists), it is NOT a * global singleton, but a per-implementation singleton. For this reason, you * must call verto_free() when you are done with this loop. Even after calling * verto_free() on the default verto_ctx, you can safely call verto_default() * again and receive a new reference to the same (internally default) loop. * * In all other respects, verto_default() acts exactly like verto_new(). * * @see verto_new() * @see verto_free() * @param impl The implementation to use, or NULL. * @param reqtypes A bitwise or'd list of required event type features. * @return The default verto_ctx, or NULL on error. Call verto_free() when done. */ verto_ctx * verto_default(const char *impl, verto_ev_type reqtypes); /** * Sets the default implementation to use by its name. * * This function returns 1 on success and 0 on failure. It can fail for the * following reasons: * 1. The default implementation was already set via verto_set_default(). * 2. The implementation specified could not be found. * 3. The implementation specified didn't support the features specified. * 4. The impl argument was NULL. * 5. verto_new() was already called. * 6. verto_default() was already called. * 7. verto_new_NAME() was already called. * 8. verto_default_NAME() was already called. * 9. verto_convert_NAME() was already called. * * @see verto_new() * @see verto_default() * @param impl The implementation to use. * @param reqtypes A bitwise or'd list of required event type features. * @return The default verto_ctx, or NULL on error. Call verto_free() when done. */ int verto_set_default(const char *impl, verto_ev_type reqtypes); /** * Sets the allocator to use for verto_ctx and verto_ev objects. * * If you plan to set the allocator, you MUST call this function before any * other verto_*() calls. * * @see verto_new() * @see verto_default() * @see verto_add_io() * @see verto_add_timeout() * @see verto_add_idle() * @see verto_add_signal() * @see verto_add_child() * @param resize The allocator to use (behaves like realloc(); * resize(ptr, 0) must free memory at ptr.) * @param hierarchical Zero if the allocator is not hierarchical */ int verto_set_allocator(void *(*resize)(void *mem, size_t size), int hierarchical); /** * Frees a verto_ctx. * * When called on a default verto_ctx, the reference will be freed but the * internal default loop will still be available via another call to * verto_default(). * * @see verto_new() * @see verto_default() * @param ctx The verto_ctx to free. */ void verto_free(verto_ctx *ctx); /** * Frees global state. * * Remove and free all allocated global state. Call only when no further * contexts exist and all threads have exited. * * @see verto_new() * @see verto_free() * @see verto_default() */ void verto_cleanup(void); /** * Run the verto_ctx forever, or at least until verto_break() is called. * * @see verto_break() * @param ctx The verto_ctx to run. */ void verto_run(verto_ctx *ctx); /** * Run the verto_ctx once. May block. * * @param ctx The verto_ctx to run once. */ void verto_run_once(verto_ctx *ctx); /** * Exits the currently running verto_ctx. * * @see verto_run() * @param ctx The verto_ctx to exit. */ void verto_break(verto_ctx *ctx); /** * Re-initializes the verto_ctx. * * This function deletes all events, except those which have set the * VERTO_EV_FLAG_REINITIABLE flag. If you fork(), you MUST call this in the * child process after the fork! * * If this function fails it indicates that at least one * VERTO_EV_FLAG_REINITIABLE event was not rearmed or that ctx was NULL. * * @see verto_new() * @see verto_default() * @param ctx The verto_ctx to re-initialize. * @return Non-zero on success, 0 on error. */ int verto_reinitialize(verto_ctx *ctx); /** * Adds a callback executed when a file descriptor is ready to be read/written. * * All verto_ev events are automatically freed when their parent verto_ctx is * freed. You do not need to free them manually. If VERTO_EV_FLAG_PERSIST is * provided, the event will repeat until verto_del() is called. If * VERTO_EV_FLAG_PERSIST is not provided, the event will be freed automatically * after its execution. In either case, you may call verto_del() at any time * to prevent the event from executing. * If VERTO_EV_FLAG_IO_CLOSE_FD is provided the passed in fd is automatically * closed when the event is freed with verto_del() * * NOTE: On Windows, the underlying select() only works with sockets. As such, * any attempt to add a non-socket io event on Windows will produce undefined * results and may even crash. * * @see verto_del() * @param ctx The verto_ctx which will fire the callback. * @param flags The flags to set (at least one VERTO_EV_FLAG_IO* required). * @param callback The callback to fire. * @param fd The file descriptor to watch for reads. * @return The verto_ev registered with the event context or NULL on error. */ verto_ev * verto_add_io(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, int fd); /** * Adds a callback executed after a period of time. * * All verto_ev events are automatically freed when their parent verto_ctx is * freed. You do not need to free them manually. If VERTO_EV_FLAG_PERSIST is * provided, the event will repeat until verto_del() is called. If * VERTO_EV_FLAG_PERSIST is not provided, the event will be freed automatically * after its execution. In either case, you may call verto_del() at any time * to prevent the event from executing. * * @see verto_del() * @param ctx The verto_ctx which will fire the callback. * @param flags The flags to set. * @param callback The callback to fire. * @param interval Time period to wait before firing (in milliseconds). * @return The verto_ev registered with the event context. */ verto_ev * verto_add_timeout(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, time_t interval); /** * Adds a callback executed when there is nothing else to do. * * All verto_ev events are automatically freed when their parent verto_ctx is * freed. You do not need to free them manually. If VERTO_EV_FLAG_PERSIST is * provided, the event will repeat until verto_del() is called. If * VERTO_EV_FLAG_PERSIST is not provided, the event will be freed automatically * after its execution. In either case, you may call verto_del() at any time * to prevent the event from executing. * * @see verto_del() * @param ctx The verto_ctx which will fire the callback. * @param flags The flags to set. * @param callback The callback to fire. * @return The verto_ev registered with the event context. */ verto_ev * verto_add_idle(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback); /** * Adds a callback executed when a signal is received. * * All verto_ev events are automatically freed when their parent verto_ctx is * freed. You do not need to free them manually. If VERTO_EV_FLAG_PERSIST is * provided, the event will repeat until verto_del() is called. If * VERTO_EV_FLAG_PERSIST is not provided, the event will be freed automatically * after its execution. In either case, you may call verto_del() at any time * to prevent the event from executing. * * NOTE: If you attempt to ignore a signal without the VERTO_EV_FLAG_PERSIST * flag, this function fails. * * NOTE: SIGCHLD is expressly not supported. If you want this notification, * please use verto_add_child(). * * WARNNIG: Signal events can only be reliably received in the default verto_ctx * in some implementations. Attempting to receive signal events in non-default * loops may result in assert() failures. * * WARNING: While verto does its best to protect you from crashes, there is * essentially no way to do signal events if you mix multiple implementations in * a single process. Attempting to do so will result in undefined behavior, * and potentially even a crash. You have been warned. * * @see verto_add_child() * @see verto_repeat() * @see verto_del() * @param ctx The verto_ctx which will fire the callback. * @param flags The flags to set. * @param callback The callback to fire. * @param signal The signal to watch for. * @return The verto_ev registered with the event context. */ verto_ev * verto_add_signal(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, int signal); /** * Adds a callback executed when a child process exits. * * This event will be freed automatically after its execution. Due to the * nature of a process' life-cycle, child events cannot persist (processes only * exit once). This function returns NULL if you attempt to use * VERTO_EV_FLAG_PERSIST. You may, of course, call verto_del() at any time to * prevent the callback from firing. * * @see verto_del() * @param ctx The verto_ctx which will fire the callback. * @param flags The flags to set. * @param callback The callback to fire. * @param child The pid (POSIX) or handle (Win32) of the child to watch for. * @return The verto_ev registered with the event context. */ verto_ev * verto_add_child(verto_ctx *ctx, verto_ev_flag flags, verto_callback *callback, verto_proc proc); /** * Sets the private pointer of the verto_ev. * * The free callback will be called in two cases: * 1. When the event is deleted (manually or automatically) * 2. When verto_set_private() is called again, unless * free is NULL. * * @see verto_get_private() * @param ev The verto_ev * @param priv The private value to store * @param free The callback used to free the data or NULL */ void verto_set_private(verto_ev *ev, void *priv, verto_callback *free); /** * Gets the private pointer of the verto_ev. * * @see verto_set_private() * @param ev The verto_ev * @return The verto_ev private pointer */ void * verto_get_private(const verto_ev *ev); /** * Gets the type of the verto_ev. * * @see verto_add_io() * @see verto_add_timeout() * @see verto_add_idle() * @see verto_add_signal() * @see verto_add_child() * @param ev The verto_ev * @return The verto_ev type */ verto_ev_type verto_get_type(const verto_ev *ev); /** * Gets the flags associated with the given verto_ev. * * @see verto_add_io() * @see verto_add_timeout() * @see verto_add_idle() * @see verto_add_signal() * @see verto_add_child() * @see verto_set_flags() * @param ev The verto_ev * @return The verto_ev type */ verto_ev_flag verto_get_flags(const verto_ev *ev); /** * Sets the flags associated with the given verto_ev. * * See _VERTO_EV_FLAG_MUTABLE_MASK for the flags that can be changed * with this function. All others will be ignored. If the flags specified * are the same as the flags the event already has, this function is a no-op. * * @see verto_add_io() * @see verto_add_timeout() * @see verto_add_idle() * @see verto_add_signal() * @see verto_add_child() * @see verto_get_flags() * @param ev The verto_ev * @param flags The flags for the event */ void verto_set_flags(verto_ev *ev, verto_ev_flag flags); /** * Gets the file descriptor associated with a read/write verto_ev. * * @see verto_add_io() * @param ev The verto_ev to retrieve the file descriptor from. * @return The file descriptor, or -1 if not a read/write event. */ int verto_get_fd(const verto_ev *ev); /** * Gets the file descriptor state from when the event fires. * * @see verto_add_io() * @param ev The verto_ev to retrieve the fd state from. * @return The fd state. */ verto_ev_flag verto_get_fd_state(const verto_ev *ev); /** * Gets the interval associated with a timeout verto_ev. * * @see verto_add_timeout() * @param ev The verto_ev to retrieve the interval from. * @return The interval, or 0 if not a timeout event. */ time_t verto_get_interval(const verto_ev *ev); /** * Gets the signal associated with a signal verto_ev. * * @see verto_add_signal() * @param ev The verto_ev to retrieve the signal from. * @return The signal, or -1 if not a signal event. */ int verto_get_signal(const verto_ev *ev); /** * Gets the process associated with a child verto_ev. * * @see verto_add_child() * @param ev The verto_ev to retrieve the process from. * @return The pid/handle, or 0/NULL if not a child event (POSIX/Win32). */ verto_proc verto_get_proc(const verto_ev *ev); /** * Gets the status of the process which caused this event to fire. * * @see verto_add_child() * @param ev The verto_ev to retrieve the status from. * @return The pid/handle status. */ verto_proc_status verto_get_proc_status(const verto_ev *ev); /** * Gets the verto_ctx associated with a verto_ev. * * This is a borrowed reference, don't attempt to free it! * * @param ev The verto_ev to retrieve the verto_ctx from. * @return The verto_ctx. */ verto_ctx * verto_get_ctx(const verto_ev *ev); /** * Removes an event from from the event context and frees it. * * The event and its contents cannot be used after this call. * * @see verto_add_io() * @see verto_add_timeout() * @see verto_add_idle() * @see verto_add_signal() * @see verto_add_child() * @param ev The event to delete. */ void verto_del(verto_ev *ev); /** * Returns the event types supported by this implementation. * * @param ctx The verto_ctx to query. * @return The event types supported. */ verto_ev_type verto_get_supported_types(verto_ctx *ctx); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* VERTO_H_ */ libverto-0.3.1/tests/000077500000000000000000000000001343534721300145105ustar00rootroot00000000000000libverto-0.3.1/tests/Makefile.am000066400000000000000000000007631343534721300165520ustar00rootroot00000000000000AUTOMAKE_OPTIONS = parallel-tests color-tests LDADD = $(abs_top_builddir)/src/libverto.la AM_LDFLAGS = -rpath $(abs_top_builddir)/src/.libs AM_CFLAGS = -Wall -I$(abs_top_srcdir)/src if MODULE_GLIB AM_CFLAGS += -DHAVE_GLIB=1 endif if MODULE_LIBEV AM_CFLAGS += -DHAVE_LIBEV=1 endif if MODULE_LIBEVENT AM_CFLAGS += -DHAVE_LIBEVENT=1 endif if MODULE_TEVENT AM_CFLAGS += -DHAVE_TEVENT=1 endif check_PROGRAMS = timeout idle child signal read write EXTRA_DIST = test.h TESTS = $(check_PROGRAMS) libverto-0.3.1/tests/child.c000066400000000000000000000047731343534721300157520ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include "test.h" #define EXITCODE 17 static int exitstatus; static int freed; void exit_cb(verto_ctx *ctx, verto_ev *ev) { (void) ctx; (void) ev; if (WEXITSTATUS(exitstatus) != EXITCODE) { printf("ERROR: Child event never fired!\n"); retval = 1; } if (!freed) { printf("ERROR: On free never fired!\n"); retval = 1; } verto_break(ctx); } void onfree(verto_ctx *ctx, verto_ev *ev) { (void) ctx; (void) ev; freed = 1; } void cb(verto_ctx *ctx, verto_ev *ev) { (void) ctx; (void) ev; exitstatus = verto_get_proc_status(ev); } int do_test(verto_ctx *ctx) { pid_t pid; verto_ev *ev; exitstatus = 0; freed = 0; if (!(verto_get_supported_types(ctx) & VERTO_EV_TYPE_CHILD)) { printf("WARNING: Child not supported!\n"); verto_break(ctx); return 0; } pid = fork(); if (pid < 0) return 1; else if (pid == 0) { usleep(50000); /* 0.05 seconds */ exit(EXITCODE); } /* Persist makes no sense for children events */ assert(!verto_add_child(ctx, VERTO_EV_FLAG_PERSIST, cb, pid)); assert(verto_add_timeout(ctx, VERTO_EV_FLAG_NONE, exit_cb, 1000)); ev = verto_add_child(ctx, VERTO_EV_FLAG_NONE, cb, pid); assert(ev); verto_set_private(ev, NULL, onfree); return 0; } libverto-0.3.1/tests/idle.c000066400000000000000000000047001343534721300155720ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "test.h" static int callcount; void exit_cb(verto_ctx *ctx, verto_ev *ev) { (void) ctx; (void) ev; retval = 1; switch (callcount) { case 0: printf("ERROR: Idle (persist) did not fire!\n"); break; case 1: printf("ERROR: Idle (persist) did not recur!\n"); break; case 2: printf("ERROR: Idle (non-persist) did not fire!\n"); break; case 3: printf("ERROR: Idle on free did not fire!\n"); break; case 4: retval = 0; break; default: break; } verto_break(ctx); } void onfree(verto_ctx *ctx, verto_ev *ev) { (void) ctx; (void) ev; ++callcount; } void cb(verto_ctx *ctx, verto_ev *ev) { if (++callcount == 2) { verto_ev *newev = verto_add_idle(ctx, VERTO_EV_FLAG_NONE, cb); verto_set_private(newev, NULL, onfree); assert(newev); verto_del(ev); } } int do_test(verto_ctx *ctx) { callcount = 0; if (!(verto_get_supported_types(ctx) & VERTO_EV_TYPE_IDLE)) { printf("WARNING: Idle not supported!\n"); verto_break(ctx); return 0; } assert(verto_add_idle(ctx, VERTO_EV_FLAG_PERSIST, cb)); assert(verto_add_timeout(ctx, VERTO_EV_FLAG_NONE, exit_cb, 1000)); return 0; } libverto-0.3.1/tests/read.c000066400000000000000000000051771343534721300156010ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include #include "test.h" #define DATA "hello" #define DATALEN 5 static int fds[2]; static int callcount = 0; static void timeout_cb(verto_ctx *ctx, verto_ev *ev) { (void) ev; printf("ERROR: Timeout!\n"); if (fds[0] >= 0) close(fds[0]); if (fds[1] >= 0) close(fds[1]); retval = 1; verto_break(ctx); } static void cb(verto_ctx *ctx, verto_ev *ev) { unsigned char buff[DATALEN]; int fd = 0; ssize_t bytes = 0; fd = verto_get_fd(ev); assert(fd == fds[0]); bytes = read(fd, buff, DATALEN); if (callcount++ == 0) { assert(verto_get_fd_state(ev) & VERTO_EV_FLAG_IO_READ); assert(bytes == DATALEN); close(fds[1]); fds[1] = -1; } else { if (!(verto_get_fd_state(ev) & VERTO_EV_FLAG_IO_ERROR)) printf("WARNING: VERTO_EV_FLAG_IO_ERROR not supported!\n"); assert(bytes != DATALEN); close(fd); fds[0] = -1; verto_del(ev); verto_break(ctx); } } int do_test(verto_ctx *ctx) { callcount = 0; fds[0] = -1; fds[1] = -1; assert(verto_get_supported_types(ctx) & VERTO_EV_TYPE_IO); assert(pipe(fds) == 0); assert(verto_add_timeout(ctx, VERTO_EV_FLAG_NONE, timeout_cb, 1000)); assert(verto_add_io(ctx, VERTO_EV_FLAG_PERSIST | VERTO_EV_FLAG_IO_READ, cb, fds[0])); assert(write(fds[1], DATA, DATALEN) == DATALEN); return 0; } libverto-0.3.1/tests/signal.c000066400000000000000000000055031343534721300161340ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include "test.h" static int count; void exit_cb(verto_ctx *ctx, verto_ev *ev) { if ((pid_t) (uintptr_t) verto_get_private(ev) != 0) waitpid((pid_t) (uintptr_t) verto_get_private(ev), NULL, 0); switch (count) { case 0: printf("ERROR: Signal callback never fired!\n"); break; case 1: printf("ERROR: Signal MUST recur!\n"); break; default: break; } retval = count != 2; verto_break(ctx); } void cb(verto_ctx *ctx, verto_ev *ev) { (void) ctx; (void) ev; count++; } int do_test(verto_ctx *ctx) { verto_ev *ev; pid_t pid = 0; count = 0; if (!(verto_get_supported_types(ctx) & VERTO_EV_TYPE_SIGNAL)) { printf("WARNING: Signal not supported!\n"); verto_break(ctx); return 0; } /* We should get a failure when trying to create a non-persistent ignore */ assert(!verto_add_signal(ctx, VERTO_EV_FLAG_NONE, VERTO_SIG_IGN, SIGUSR2)); assert(verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, cb, SIGUSR1)); assert(verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, VERTO_SIG_IGN, SIGUSR2)); pid = fork(); if (pid < 0) return 1; else if (pid == 0) { usleep(10000); /* 0.01 seconds */ kill(getppid(), SIGUSR1); usleep(10000); /* 0.01 seconds */ kill(getppid(), SIGUSR1); usleep(10000); /* 0.01 seconds */ kill(getppid(), SIGUSR2); exit(0); } ev = verto_add_timeout(ctx, VERTO_EV_FLAG_NONE, exit_cb, 1000); assert(ev); verto_set_private(ev, (void *) (uintptr_t) pid, NULL); return 0; } libverto-0.3.1/tests/test.h000066400000000000000000000045731343534721300156510ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include static char *MODULES[] = { #ifdef BUILTIN_MODULE #define __str(s) #s #define _str(s) __str(s) _str(BUILTIN_MODULE), #undef _str #undef __str #endif #ifdef HAVE_GLIB "glib", #endif #ifdef HAVE_LIBEV "libev", #endif #ifdef HAVE_LIBEVENT "libevent", #endif #ifdef HAVE_TEVENT "tevent", #endif NULL, NULL, }; int do_test(verto_ctx *ctx); static int retval = 0; int main(int argc, char **argv) { int i; verto_ctx *ctx; if (argc == 2) { MODULES[0] = argv[1]; MODULES[1] = NULL; } for (i=0 ; MODULES[i] ; i++) { printf("Module: %s\n", MODULES[i]); assert((ctx = verto_default(MODULES[i], VERTO_EV_TYPE_NONE))); retval = do_test(ctx); if (retval != 0) { verto_free(ctx); return retval; } verto_run(ctx); verto_free(ctx); if (retval != 0) break; } verto_cleanup(); return retval; } void *passert(void *p) { assert(p); return p; } #define new0(type) _new0(sizeof(type)) void * _new0(ssize_t size) { void *p = malloc(size); return passert(p ? memset(p, 0, size) : p); } libverto-0.3.1/tests/timeout.c000066400000000000000000000047161343534721300163520ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include "test.h" /* The glib timer will subtract a perterbation of up to 10ms based on your * DBUS session or HOSTNAME (see g_timeout_set_expiration). */ #define SLEEP 10 #define SLEEP_MIN (SLEEP-10) #define SLEEP_MAX (SLEEP*4) #define M2U(m) ((m) * 1000) static int callcount; struct timeval starttime; static char elapsed(time_t min, time_t max) { struct timeval tv; long long diff; assert(gettimeofday(&tv, NULL) == 0); diff = (tv.tv_sec - starttime.tv_sec) * M2U(1000) + tv.tv_usec - starttime.tv_usec; assert(gettimeofday(&starttime, NULL) == 0); if (diff < M2U(min) || diff > M2U(max)) { printf("ERROR: Timeout is out-of-bounds!\n"); return 0; } return 1; } static void exit_cb(verto_ctx *ctx, verto_ev *ev) { (void) ev; assert(callcount == 3); verto_break(ctx); } static void cb(verto_ctx *ctx, verto_ev *ev) { assert(elapsed(SLEEP_MIN, SLEEP_MAX)); if (++callcount == 3) assert(verto_add_timeout(ctx, VERTO_EV_FLAG_NONE, exit_cb, SLEEP*2)); else if (callcount == 2) { assert(verto_add_timeout(ctx, VERTO_EV_FLAG_NONE, cb, SLEEP)); verto_del(ev); } } int do_test(verto_ctx *ctx) { callcount = 0; assert(gettimeofday(&starttime, NULL) == 0); assert(verto_add_timeout(ctx, VERTO_EV_FLAG_PERSIST, cb, SLEEP)); return 0; } libverto-0.3.1/tests/write.c000066400000000000000000000057231343534721300160150ustar00rootroot00000000000000/* * Copyright 2011 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include #include "test.h" #define DATA "hello" #define DATALEN 5 static int fds[2]; static int callcount = 0; static void timeout_cb(verto_ctx *ctx, verto_ev *ev) { (void) ev; printf("ERROR: Timeout!\n"); if (fds[0] >= 0) close(fds[0]); if (fds[1] >= 0) close(fds[1]); retval = 1; verto_break(ctx); } static void error_cb(verto_ctx *ctx, verto_ev *ev) { int fd = 0; /* When we get here, the fd should be closed, so an error should occur */ fd = verto_get_fd(ev); if (!(verto_get_fd_state(ev) & VERTO_EV_FLAG_IO_ERROR)) printf("WARNING: VERTO_EV_FLAG_IO_ERROR not supported!\n"); assert(write(fd, DATA, DATALEN) != DATALEN); close(fd); fds[1] = -1; verto_break(ctx); } static void read_cb(verto_ctx *ctx, verto_ev *ev) { unsigned char buff[DATALEN]; int fd = verto_get_fd(ev); assert(read(fd, buff, DATALEN) == DATALEN); close(fd); fds[0] = -1; assert(verto_add_io(ctx, VERTO_EV_FLAG_IO_WRITE, error_cb, fds[1])); } static void write_cb(verto_ctx *ctx, verto_ev *ev) { int fd = 0; fd = verto_get_fd(ev); assert(verto_get_fd_state(ev) & VERTO_EV_FLAG_IO_WRITE); assert(write(fd, DATA, DATALEN) == DATALEN); assert(verto_add_io(ctx, VERTO_EV_FLAG_IO_READ, read_cb, fds[0])); } int do_test(verto_ctx *ctx) { callcount = 0; fds[0] = -1; fds[1] = -1; assert(verto_get_supported_types(ctx) & VERTO_EV_TYPE_IO); if (!verto_add_signal(ctx, VERTO_EV_FLAG_NONE, VERTO_SIG_IGN, SIGPIPE)) signal(SIGPIPE, SIG_IGN); assert(pipe(fds) == 0); assert(verto_add_timeout(ctx, VERTO_EV_FLAG_NONE, timeout_cb, 1000)); assert(verto_add_io(ctx, VERTO_EV_FLAG_IO_WRITE, write_cb, fds[1])); return 0; }