Git Product home page Git Product logo

ocean's Introduction

Description CI

Ocean is a general purpose library, compatible with both D1 and D2, with a focus on supporting the development of high-performance, real-time applications. This focus has led to several noteworthy design choices:

  • Ocean is not cross-platform. The only supported platform is Linux.
  • Ocean assumes a single-threaded environment. Fiber-based multi-tasking is favoured, internally.
  • Ocean aims to minimise use of the D garbage collector. GC collect cycles can be very disruptive to real-time applications, so Ocean favours a model of allocating resources once then reusing them, wherever possible.

Ocean began life as an extension of Tango, some elements of which were eventually merged into Ocean.

D2 Compatibility

Since v5.0.0, Ocean is a D2-only library.

Build / Use

Dependencies

This library has quite a number of dependencies, but it depends on which modules you want to use. Usually the easiest way to find out is just using it and see which libraries the linker fails to find and then install by demand.

If you want to install everything, then the list is as follows (for an absolutely up to date list you can take a look at the Build.mak file, in the $O/%unittests target):

  • -lglib-2.0
  • -lpcre
  • -lxml2
  • -lxslt
  • -lebtree
  • -lreadline
  • -lhistory
  • -llzo2
  • -lbz2
  • -lz
  • -ldl
  • -lgcrypt
  • -lgpg-error
  • -lrt

To install those dependencies on Ubuntu refer to the apt-get install command in docker/build.

Please note that ebtree is not the vanilla upstream version. We created our own fork of it to be able to write D bindings more easily. You can find the needed ebtree library in https://github.com/sociomantic-tsunami/ebtree/releases (look only for the v6.0.socioX releases, some pre-built Ubuntu packages are provided).

If you plan to use the provided Makefile (you need it to convert code to D2, or to run the tests), you need to also checkout the submodules with git submodule update --init. This will fetch the Makd project in submodules/makd.

Versioning

ocean's versioning follows Neptune.

This means that the major version is increased for breaking changes, the minor version is increased for feature releases, and the patch version is increased for bug fixes that don't cause breaking changes.

Support Guarantees

  • Major branch development period: 6 months
  • Maintained minor versions: 2 most recent

Maintained Major Branches

Major Initial release date Supported until
v5.x.x v5.0.0: 04/04/2019 TBD

Releases

Latest release notes | All releases

Releases are handled using GitHub releases. The notes associated with a major or minor github release are designed to help developers to migrate from one version to another. The changes listed are the steps you need to take to move from the previous version to the one listed.

The release notes are structured in 3 sections, a Migration Instructions, which are the mandatory steps that users have to do to update to a new version, Deprecated which contains deprecated functions that are recommended not to use but will not break any old code, and the New Features which are optional new features available in the new version that users might find interesting. Using them is optional, but encouraged.

Contributing

See the guide for contributing to Neptune-versioned libraries.

ocean's People

Contributors

andrew-stevenson-sociomantic avatar ben-palmer-sociomantic avatar bogdan-szabo-sociomantic avatar burak-tutanlar-sociomantic avatar david-eckardt-frequenz avatar david-eckardt-sociomantic avatar don-clugston-sociomantic avatar gautam-kotian-sociomantic avatar geod24 avatar gkotian avatar jens-mueller-sociomantic avatar joseph-wakeling-frequenz avatar joseph-wakeling-sociomantic avatar kinke avatar leandro-lucarella-sociomantic avatar llucax avatar martinnowak avatar mathias-baumann-sociomantic avatar mathias-lang-sociomantic avatar matthias-wende-sociomantic avatar mihails-strasuns-sociomantic avatar nemanja-boric-sociomantic avatar oraby avatar rainers avatar razvann7 avatar scott-gibson-sociomantic avatar stefan-brus-sociomantic avatar stefan-koch-sociomantic avatar tiyash-basu-sociomantic avatar vasileios-karavasilis-sociomantic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ocean's Issues

Deprecate ocean.text.convert.{Format,Layout,Layout_tango}

Those modules have been replaced by ocean.text.convert.Formatter and should be deprecated as they don't play well with D2.
Format depends on Layout_tango, as does Layout.

Once #203 and #187 have been pulled, we will be able to deprecate Layout_tango. As 203 includes a breaking change, this will only happen in v4.0.0 at best.

Feel free to assign me.

Allow to reconfigure loggers live from UnixSocket

Now that we have UnixSocket support in DaemonApp, it would be nice to get a set of basic commands in (which can be overriden / skipped if the dev wants to).

One of those would be the ability to change logger configurations live, so one can temporarily enable / disable some loggers for debugging purpose.

Provide an ocean-d2 repo

Currently if you have a D2 only application and you decided to use ocean then you have to do the following:

  • Make sure that you have d1to2fix installed on your system
  • Add Ocean as a submodule
  • Go to the ocean submodule directory and checkout the desired branch
  • Add Makd as a submodule to ocean
  • Run make d2conv
  • If your project is under version-control, then you need to commit the converted code so you can have none-dirty commits.
  • And only at that point you are ready to use ocean.

The above procedure may deter a lot of D2 users who would like to test Ocean. It would be much more convenient to have a new ocean-d2 repo that contains converted snapshots of the released tags of this repo.
Syncing the d2 repo can be automatically maintained by Travis.
Also, I don't know if current ocean is in dub, but certainly the converted Ocean can live there.

fyi @leandro-lucarella-sociomantic


Disclaimer: I'm a direct beneficiary of this issue. I will give a (2x-slot-)lightning talk about Ocean in DConf. I'd like the ease of using Ocean to be one of the selling points.

StringC.toCString can be Inout

It should be possible to change toCString from

public static char* toCString ( ref mstring str )

to

public static Inout!(char)* toCString ( ref Inout!(char)[] str )

Because the implementation does not rely on str being mutable. Having it as Inout allows passing cstrings or even istrings.

Note this also applies to the Wchar overload.

Add void sink delegate support to Formatter

The return value of the sink delegate (size_t delegate ( cstring chunk )) is currently unused. For more convenient usage, it'd be nice for Formatter to support void sink delegates.

Task.await() with timeout

There are many situations where you want to wait for a Task to finish or a certain time to pass. (e.g. connecting to a server with some bail-out logic if the connection isn't promptly established.)

Logger: Assess the possibility of providing the appenders directly to `sformat`

Currently every Logger allocates 2kB of data:

this.buffer_ = new mstring(2048);

This is used by the Logger.format. However this introduces a limit in the output message, and an extra copy during logging.

I think with the Formatter approach of using delegates we should be able to directly output to the Appender(s), saving the memory allocation, the extra copy, and removing the limitation to 2048 char (or whatever the buffer length is).

Make ocean.text.Search non-templated

@don-clugston-sociomantic commented on an internal sociomantic project:

The functions in ocean.text.Search are templated on the character type T. The constructor (actually opCall) takes this type from the parameter of the string passes to it. If it's a string literal it will be immutable char and if a variable it will be char. This is never what you want. Probably this could fixed by throwing Unqual everywhere in that module, but I don't think there's much point.

Those Fructs were originally created to work around bugs in D's template instantiation, which forced you to explicitly specify the types. The bugs were fixed about a decade ago. Now the Fructs do the opposite, they create type mismatch problems! And that's the only thing they do. They don't do anything useful.

It is probably best to deprecate and later remove this module to prevent someone from trying to use it.

cc @mathias-lang-sociomantic

`TimerExt` should allow for GC-free allocations

Currently, TimerExt of DaemonApp is based on the TimerSet, which with few more inheritance layer goes back to TimeoutManager. TimeoutManager by default uses BucketElementGCAllocator for allocating internals, which uses GC to allocate.

However, TimeoutManager allows for configuring this, so another allocation strategies may be used, such malloc/free via BucketElementMallocAllocator, for example.

For the applications which want to avoid GC activity, it should be allowed to use some strategy other than BucketElementGCAllocator.

Reduce CodeCov noise to signal ratio

CodeCov as it is, is not being very useful, as we get red PRs that are OK.

I know there is #204, but it seems other project had issues with it, so maybe we can analyse taking similar steps.

UnixSocket: Let handlers interact with users

Working on #37 I found myself wishing a way to interact with the user. Currently commands are one-shot: One send a command, an action is performed and one or multiple messages are sent back.

However, certain actions are complex or dangerous, in which case the handler might want to interact with the user. For example, here's an example of using adduser:

% sudo adduser test
Adding user `test' ...
Adding new group `test' (1002) ...
Adding new user `test' (1001) with group `test' ...
The home directory `/home/test' already exists.  Not copying from `/etc/skel'.
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for test
Enter the new value, or press ENTER for the default
	Full Name []: Test
	Room Number []: 42   
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] Y

In the case of reconfiguring loggers it's even more sensible, because one might just want to change the logger level. However, the config currently allow to:

  • Change the level
  • Toggle write to console
  • Change the file the logger is writing to
  • Change the console layout
  • Change the file layout
  • Propagate settings

While it is possible to handle this via a variety of method, a mean to interact with the user would be welcome. However, AFAICS it would require some redesign of UnixSocketHandler.

Base64 decoding of unpadded data leads to incomplete decoded data.

Extending the following unit test to check for the decoding of padded data shows that the decoding is broken.

https://github.com/sociomantic-tsunami/ocean/blob/v2.x.x/src/ocean/util/encode/Base64.d#L514

// Encode without padding
unittest
{
    istring str = "Hello, how are you today?";
    Const!(ubyte)[] payload = cast(Const!(ubyte)[]) str;
    cstring result = encode(payload, false);
    test!("==")(result, "SGVsbG8sIGhvdyBhcmUgeW91IHRvZGF5Pw");

  
    auto decoded = cast(cstring)decode(result);
    test!("==")(decoded, str);
}

results in

./src/ocean/util/encode/Base64.d:521: test error: expression 'Hello, how are you today == Hello, how are you today?' evaluates to false

Flakey tests in random modules

After we added code coverage checks, it started to complain sporadically about unexpected changes in few modules, most often src/ocean/math/random/engines/KissCmwc.d. Initially I dismissed it as either codecov or dmd bug, but recently I have realized that it is becomes those are tested with actual random seed and resulting coverage is not deterministic.

Fix docker cache for travis builds

Right now for some reason travis seems to be failing to cache the images that we pull and push to the docker registry to work as a cache, thus making the whole pulling and pushing just another time drain.

I already contacted Travis CI and they gave me some sort of experimental SSH access to the VM a job was run on, so I will be able to debug this and hopefully find a solution.

Since to be able to test this I need also for the docker pull/push is in a branch (PRs are not trusted with docker credentials), for now we should not disable the pull/push until I can have some time to investigate this. FYI @mihails-strasuns-sociomantic

D2: Push converted D2 tags to this repo instead of ocean-d2

The double-repo approach doesn't scale, so we'll use the same repo and just push tags with a +d2 build metadata information appended to the version (so tag v2.3.4 --- conversion D2 ---> v2.3.4+d2).

For reference, this is the PR that introduced the conversion and pushing: #100

Imported symbols cannot be exposed through aggregate

Thanks to the new import rules in 2.071.0+, the design of LibFeatures doesn't work.

The definition is currently:

module ocean.LibFeatures;

static immutable has_features_2_7 = true;
static immutable has_features_2_6 = true;
static immutable has_features_2_5 = true;
static immutable has_features_2_4 = true;
static immutable has_features_2_3 = true;
static immutable has_features_2_1 = true;
static immutable has_features_2_0 = true;

And the usage is:

private bool hasFeaturesFromFunc ( istring libname, ulong major, ulong minor ) ()
{
    struct Library
    {
        mixin("import " ~ libname ~ ".LibFeatures;");
    }

   // Generates `return is(typeof(Library.has_features_2_0));` for example
    mixin("return is(typeof(Library.has_features_"
        ~ ctfe_i2a(major) ~ "_" ~ ctfe_i2a(minor) ~ "));");
}

However this doesn't work with new import rules, which make import scope not accessible from outside of an aggregate.
CC @mihails-strasuns-sociomantic

Formatter must never format arrays as `null`

void main ()
{
    int[] arr;
    Stdout.print(format("{}\n", arr));

    arr = new int[5];
    arr.length = 0;
    Stdout.print(format("{}\n", arr));
}

This code must print [] twice. Right now it has special case for arr.ptr is null and will print null for a first call.

As this is a subtle breaking change, scheduling it to v4.0.0 for now.

Ocean must pass tests when run with `-release`

Essentially another form of the goal to clean up assert usage in ocean to make -release flag feasible for our applications. Right now it doesn't even pass tests because some failed assertions are checked with testThrown.

ocean.util.log.Logger truncates in a way that Log did not

Writing to a logger using ocean.util.log.Log ultimately does this:

Logger format (Level level, cstring fmt, TypeInfo[] types, ArgList args)
        {
                if (types.length)
                {
                    if (buffer_ is null)
                        formatWithDefaultBuffer(level, fmt, types, args);
                    else
                        formatWithProvidedBuffer(level, fmt, types, args);
                }
                else
                   append (level, fmt);
                return this;
        }

Note that if no types are provided, it simply does an append rather than formatting the string.
Logger behaves differently. It always formats. This means that it uses the buffer, which means the string is truncated at 2048 characters.

Enhance Buffer to minimise calls to `enableStomping` / `assumeSafeAppend`

Code like the following is very common:

void doSomethingWithMyArray ( ref void[] buf )
{
  buf.length = 0;
  enableStomping(buf);
  fillArrayWithSomething(buf);
}

Live testing of calling such code in a tight loop has revealed that the impact of enableStomping (which, in turn, calls assumeSafeAppend) on the D2 build is significant. (One concrete example: iterating over a large database in memory and writing it out to disk was about 20% slower in the D2 build.)

One way to fix this is to never reduce the length of the referenced array and separately keep track of the actual content. (This is what AppendBuffer does, by the way.)

Buffer already handles a lot of D1/D2 array optimisation concerns (e.g. automatically calling enableStomping, where appropriate). It could probably be enhanced to support this optimisation as well, essentially merging AppendBuffer into Buffer. (We could then deprecate AppendBuffer.)

Replace format function in ocean.text.convert.Float

The ocean.text.convert.Float module defines a specialized format function that writes a formatted string of a floating point number into a provided buffer. This is used under the hood in ocean.text.convert.Formatter to handle floating-point values.

However, having this separate public format definition produces a naming clash any time anyone wants to import both ocean.text.convert.Float and ocean.text.convert.Formatter (e.g. if one wants to use, say, toFloat from the former and format from the second).

It would be better to bring floating-point formatting in under the hood inside Formatter and to deprecate the function in the Float module. In this way, Formatter becomes the single point of access for formatting variables to strings, while Float can concentrate on converting text to floating-point values.

Deprecate BigInt and implement replacement

Current tango inherited bigint implementation is absolutely useless for our goals as it allocates on mutations and doesn't have fixed binary layout. Fortunately no Sociomantic projects use it so it can be simply deprecated.

I will start working on simple replacement module ASAP.

`toDString` should accept `Const!(char)*`

The function toDString in ocean.text.util.String should be more general by accepting Const!(char)* instead of char*. Consider the case when you have a C string

Const!(char)* c_string = "test";
auto d_string = StringC.toDString(c_string); // does not compile with D2

Currently you cannot call toDString because c_string is const. You can easily end up with a const C string when calling a C library. As a work around you can copy c_string to a char*. To me the proper fix is allow passing Const!(char)* since toDString does not modify the memory pointed to by its argument. Also it is nice to indicate (via its signature) to the caller that it does not perform such modifications. Since the change accepts more input existing code is unaffected by the change.

Same reasoning holds for toDString accepting currently a Wchar*.

Check ocean.math.Probability license

As found out by http://forum.dlang.org/post/[email protected], the https://github.com/sociomantic-tsunami/ocean/blob/v2.x.x/src/ocean/math/Probability.d module original code has a different license than the stated by the D module.

This module comes from Tango: http://www.dsource.org/projects/tango/browser/trunk/tango/math/Probability.d and we kept the original copyright notice, but it might be better to check with the original author if this license change is OK.

If it's not, then this module will probably have to go.

VersionArgsExt should allow emitting versioned struct information

If you had an app that used a specific aquatic library that contained versioned structs (let's say it rhymes with brill), it would be really useful if the app emitted version information to the version log. For example:

2017-08-01 15:52:14,776 Info [ocean.util.app.ext.VersionArgsExt] - 
Moral version v2.6.3-3-g42bb468-dirty (compiled by 'NaNdrej Meetrowitch' on 
2017-08-01 15:51:58 UTC with DMD64 D Compiler v1.080.0 using 
crocodile:v5.1.0-6-g3d7e36d hashproto:v12.0.0 lunge:v4.2.0 
queueproto:v12.0.0 drill:v3.1.3 makd:v1.9.0 ocean:v3.1.3 
crowd:v4.0.1 tortoise:v7.0.1). Writing FieldProfile v3 and AdvertiserFieldProfile v2.

Make use of `IP_FREEBIND` in listeners.

from man 7 ip:

       IP_FREEBIND (since Linux 2.4)
              If enabled, this boolean option allows binding to an IP
              address that is nonlocal or does not (yet) exist.  This
              permits listening on a socket, without requiring the
              underlying network interface or the specified dynamic IP
              address to be up at the time that the application is trying to
              bind to it.  This option is the per-socket equivalent of the
              ip_nonlocal_bind /proc interface described below.

Types unsupported by ocean.text.convert.Formatter can cause mysterious compilation errors in unittest builds

e.g.:

union MyUnion
{
    int i;
    float f;
}

import ocean.core.Array : removeShift;

void func ( )
{
    MyUnion[] arr;
    removeShift(arr, 0);
}

produces this error:

./submodules/ocean/src/ocean/text/convert/Formatter.d(489): Error: static assert  "Type unsupported by ocean.text.convert.Formatter: MyUnion"
./submodules/ocean/src/ocean/text/convert/Formatter.d(475):        instantiated from here: handle!(MyUnion)
./submodules/ocean/src/ocean/text/convert/Formatter.d(203):        instantiated from here: handle!(MyUnion[])
./submodules/ocean/src/ocean/text/convert/Formatter.d(69):        instantiated from here: sformat!(MyUnion[],char[],MyUnion[])
./submodules/ocean/src/ocean/core/Enforce.d(427):        instantiated from here: format!(MyUnion[],char[],MyUnion[])
./submodules/ocean/src/ocean/core/Enforce.d(334):        instantiated from here: enforceImpl!("==",MyUnion[],MyUnion[])
./submodules/ocean/src/ocean/core/Test.d(80):        instantiated from here: enforceImpl!("==",TestException,MyUnion[],MyUnion[])
./submodules/ocean/src/ocean/core/Buffer.d(123):        instantiated from here: test!("==",MyUnion[],MyUnion[])
./submodules/ocean/src/ocean/core/array/Mutation.d(1174):        instantiated from here: Buffer!(MyUnion)
./src/myrepo/MyModule.d(1138):        instantiated from here: removeShift!(MyUnion)
make: *** [/home/devel/myrepo/build/devel/tmp/allunittests] Error 1

It's not immediately obvious to the user why calling removeShift causes unittests to fail.

Deserializer trouble with const(T[])[] struct fields

Deserializer does not correctly deserialise const(T[])[] struct fields. The problem is a qualifier-incompatible way of checking for a dynamic array in sliceSubArrays.
For the reference type qualifier inexperienced, this is how it fails:

alias const(char[])[] T;
// Check if T is an array, and if so, derive the element type:
static if (is (T V : V[]))
{
    // V is const(char)
    // Now check if T is a dynamic array:
    static if (is(V[] == T)) // compares const(char)[] with const(char[]) -- not the same
    { /* ... */ }
    else
    { /* False negative, T is a dynamic array. */ }
}

So far so good, this can be fixed. But then another problem occurs: sliceSubArrays cannot call sliceArray because the out parameter of sliceArray would need to be the array element type const(char[]) -- which is illegal, an out parameter cannot be const.
This conflict is a symptom of a more fundamental problem with deserialising const. Given a struct

struct S
{
    const(T[]) a;
}

What the deserialiser essentially does is the following:

void[] input_data;
void[] slices_buf;
S dst;
dst.a = cast(const(T[]))(slices_buf[
    0 .. numberOfElements(input_data) * const(T[]).sizeof
]);
foreach (ref element; dst.a)
{
    element = deserialiseNextElement(data);
}

The problem here is that the assignment in the foreach loop is illegal because typeof(element) is const(T[]) -- one cannot assign to const.
So what can we do here? The only options that come to my mind is to either ban such a const or cast it away when populating the array, considering slices_buf to be uninitialised memory.

Any ideas, anyone?

Serializer must process `Contiguous!(S)` fields as structs

Currently this test fails with contiguity contract violated:

unittest
{
    static struct Inner { mstring s; }
    static struct Outer { Contiguous!(Inner) inner; }

    auto s1 = Inner("abcd".dup);
    Outer s2;
    copy(s1, s2.inner);

    Contiguous!(Outer) s3; // nested contiguous struct
    copy(s2, s3);
    s3.ptr.inner.enforceIntegrity(); // fails
}
./src/ocean/util/serialize/contiguous/Contiguous.d:203: unexpected exception object.Exception: expression '0X00007F76C4F08FB8 >= 0X00007F76C4F214D8' evaluates to false

Problem happens because Contiguous struct is simply a wrapper on top of void[] from the PoV of the type system. As such, it will be serialized same as plain void[] array, as a raw sequence of bytes - meaning any internal pointers it contains won't be updated to refer to new buffer.

The only possible fix is to add special support of Contiguous structs to serializer itself, processing them as struct type instead.

Support Formatter from ocean.time.Time

Right now format("{}", someTimestamp) prints { ticks_: 636247008000000000 } instead of 03/10/17 00:00:00

Good old Tango supports it via this horror.

With the Formatter, we can just provide a toString method. Feel free to assign me.

Broken link in README

In the section D2 Compatibility, the second paragraph ends with the sentence:

The patches needed to compile the dmd-transitional compiler are located in
docker/dmd-transitional/patches.

However, the link pointed to by docker/dmd-transitional/patches is broken.

(not making a PR as I don't know what the correct link is)

Allow reloading specific files through UnixSocket

For files which are registered with ReopenableFilesExt, we need to be able to reopen a specific file via an UnixSocket command.
This should speed up the process for applications with many opened files.

For example it would be used as echo "App reopen /srv/httpd/log/root.log /srv/httpd/log/important.log" | tee /srv/httpd/httpd.socket.
@andrew-stevenson-sociomantic would that cover your needs ?

Be able to compile using upstream compiler

For now Ocean for D2 is stuck at 2.070.x, but even then there are custom modifications that are needed to be able to build / use it (this compiler is built as part of Ocean automated testing by applying patches to the upstream compiler.

These are the issues:

  • GC.stats (dlang/druntime#1610), available starting with 2.072
  • GCC 5.1 fixup (dlang/dmd#5686), available starting with 2.072
  • Extra C/POSIX bindings in druntime, available starting with 2.073
  • Add a way to get a Throwable message that can be overridden by the user (reused) without re-allocating (Ocean reuse buffers for Exception to avoid allocating at all cost).
  • #303 Remove pokemon catch
  • #306 scope with different callback type as mentioned here.
  • DMD bug

After all the issues are solved upstream, we still need to upgrade to an upstream DMD that have all the fixes, which might take a while too.

Base64 should reject badly terminated data

In case explicit padding, base64 decoder will throw an exception when there are more than two padding bytes. It should do the same when implicit padding is in use. Currently, old behavior is that it silently discards the last byte.

See #193

Create a logo for Ocean

Summary

Create a logo for Sociomantic main core library we just open-sourced called Ocean.

Brief Description

This is base library for D focused on high-performance applications. It's used to create applications that are fast and use networks mainly.

Why Ocean is cool / important?

Ocean allows developers to create fast and efficient applications. Is the core library powering the whole Sociomantic high-performance backend.

Ideas for the Logo

Obviously something oceany would be a must, but it would be nice to somehow convey also the feeling of speed, of something fast (but also vast, because the library includes a lot of different kind of utilities). Also something related to building blocks could be a possibility.

Sociomantic colours seem to be a good fit for something watery, but on the other hand there is also D involved, so red could be an option too.

Here is a similar library as an example: http://www.boost.org/

Final Output

To be used on GitHub repo, stickers, etc. potentially even external website (if one is made).

Extra Goodies

Colour scheme and suggested font for further work on a potential website.

PidLock extension should run before loggers

In case logging system doesn't have enough permission to write to the log file, it can happen that
the application fails on permission denied exception, before trying to look for the other application instance.

While this effectively prevents the application to run, it would be nice if the PidLock extension would check if the another instance is already running, before any other systems are started.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.