0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-19 18:38:21 +02:00

ircd::ctx: Preliminary trilean logic concept (WIP).

This commit is contained in:
Jason Volk 2019-09-30 12:30:57 -07:00
parent 36b621e72b
commit 01af00bae0
2 changed files with 74 additions and 0 deletions

View file

@ -104,6 +104,7 @@ namespace ircd::ctx
#include "fault.h"
#include "concurrent.h"
#include "concurrent_for_each.h"
#include "trit.h"
// Exports to ircd::
namespace ircd

73
include/ircd/ctx/trit.h Normal file
View file

@ -0,0 +1,73 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_CTX_TRIT_H
namespace ircd::ctx
{
struct trit;
}
namespace ircd
{
using ctx::trit;
}
/// Implementation of a tribool with custom semantics in a stackful coroutine
/// environment. Tribools have three states: true, false, and unknown. Our goal
/// here is to integrate this "unknown" property with the context-switching
/// system. In a nutshell, when a `trit` in an unknown state is sampled, the
/// context blocks until the `trit` leaves the unknown state. This action is
/// based on the existing promise/future system and waiting for the known state
/// can be thought of as a `future<bool>::get()`. The value of this endeavor
/// though is greater than mere syntactic sugar for future<bool>.
/// ```
/// if(trit == true) // context blocks here until the value is known
/// ... // branch taken if value==true once known.
///
/// ```
///
/// Overloaded logic operators make it possible to optimize
/// conditional predicates by employing Kleene's strong logic of indeterminacy.
/// This allows us to optimize these predicates for I/O rather than
/// computation. In the example below, traditionally under boolean logic we
/// evaluate trit[0] first, and if it's false, short-circuit evaluation elides
/// observing trit[1]:
/// ```
/// if(trit[0] && trit[1])
/// ...
///
/// ```
/// Under the trilean logic in our system, we first test if trit[0] is known,
/// because if it isn't, we can test if trit[1] is knowably false to conclude
/// the predicate. The benefit is seen when these objects represent the result
/// of latent asynchronous operations; head-of-line blocking is avoided in
/// this case because any false value can abrogate any further blocking.
///
struct ircd::ctx::trit
{
/// The boolean value state of true or false. This value is undefined when
/// `unknown` is true
bool value;
/// Whether the boolean value is determinable/determined or not. We name
/// this negatively such that any zero pre-initialization creates a known
/// false value without requiring any code to be executed.
bool unknown;
trit();
};
inline
ircd::ctx::trit::trit()
:value{false}
,unknown{false}
{}