JetBrains RD

repository·master·Indexed 19 days ago

https://github.com/jetbrains/rd

A reactive distributed communication framework for cross-process communication between .NET, Kotlin, and C++ applications, inspired by the architecture used in JetBrains Rider. The repository includes the rd-cpp C++ implementation and various third-party libraries such as CTPL (thread pool), tl::optional, tsl::ordered_map, and string-view-lite.

Tokens
16.6K
Snippets
42
Records
72
Agent score
62%

What's inside rd

  1. Overview of CTPL Thread Pool Library

    master

    CTPL is a modern, efficient, header-only C++ thread pool library designed for parallel job execution. It minimizes the overhead of creating and destroying threads and allows limiting the number of simultaneous parallel jobs.

    Key features include:

    • Header-only: No need to compile a binary library.
    • Flexible API: Supports pushing lambdas, functors, functions, and std::bind results.
    • Dynamic Control: Ability to query idle threads and resize the pool dynamically.
    • Standard C++ Integration: Uses standard C++ futures to retrieve return values and exceptions from jobs.
    • Variadic Parameters: Supports jobs with a variadic number of parameters, automatically providing the index of the thread running the object.
    • License: Apache License.
  2. What is RD?

    master
    RD is a reactive distributed communication framework designed for .NET, Kotlin, and C++ (experimental). It is inspired by the JetBrains Rider IDE and provides tools for both single-process usage and cross-process communication. The framework is structured into several layers: Lifetimes for single-process concurrency/disposal, RdFramework for networking, and RdGen for generating language-specific stubs from Kotlin DSL models.
  3. Use the utf-cpp library for UTF conversion

    master

    The utf-cpp library is a C++11 template-based, header-only library designed for converting between UTF-8, UTF-16, and UTF-32 symbols and strings. It supports Windows, Linux, and macOS.

    Platform-specific wchar_t behavior

    The library transparently maps wchar_t based on the operating system:

    • Windows: wchar_t is treated as UTF-16.
    • Linux and macOS: wchar_t is treated as UTF-32.

    Supported Encodings and Constraints

    • UTF-8: Supports 4-byte Unicode code points and 6-byte 31-bit code points.
    • UTF-32 (UCS-32): Always 1 word (4 bytes). Supports 31-bit wide code points [0‥0x7FFFFFFF].
    • UTF-16: Supports Unicode code points [0‥0x10FFFF]. It uses surrogate pairs (max 2 words/4 bytes) and prohibits the high [0xD800‥0xDBFF] and low [0xDC00‥0xDFFF] surrogate regions as standalone code points.
    // Example of converting UTF-8 to UTF-16, then to UTF-32, then back to UTF-8
    static char const u8s[] = "\xE0\xA4\xAF\xE0\xA5\x82\xE0\xA4\xA8\xE0\xA4\xBF\xE0\xA4\x95\xE0\xA5\x8B\xE0\xA4\xBD";
    using namespace ww898::utf;
    
    // UTF-8 to UTF-16
    std::u16string u16;
    convz<utf_selector_t<decltype(*u8s)>, utf16>(u8s, std::back_inserter(u16));
    
    // UTF-16 to UTF-32
    std::u32string u32;
    conv<utf16, utf_selector_t<decltype(u32)::value_type>>(u16.begin(), u16.end(), std::back_inserter(u32));
    
    // UTF-32 to UTF-8
    std::vector<char> u8;
    convz<utf32, utf8>(u32.data(), std::back_inserter(u8));
  4. How to use RdGen

    master

    RdGen is a tool used to generate model serialization and deserialization code in multiple compatible languages: C#, Kotlin, and C++ (experimental).

    To define models, you use a domain-specific language (DSL) provided as a Kotlin library. To invoke the generator, the Gradle build system is typically used.

  5. Use RdReflection for C#-first models

    master

    RdReflection is a specialized subsystem within RD designed for scenarios where models are defined primarily in C#. Unlike the standard DSL-based approach, RdReflection allows you to define all models using pure C# code.

    Key Features:

    • Pure C# Definitions: Models are written in C# rather than RD DSL files.
    • Full Entity Support: Supports all standard RD entities including RdMap, RdSet, RdCall, and RdList.
    • Live Models: Provides live models integrated with RD entities.
    • Scalar Serializers: Includes support for scalar serialization.
    • RPC Proxy Generation: Can generate proxy classes for simple RPC (Remote Procedure Call) patterns based on RdCall.

    Important Limitation:

    • No Interop: RdReflection is intended for C#-to-C# communication only. It does not support interoperability with models generated from standard RD DSL files.
  6. Use RdFramework for reactive distributed communication

    master
    The RdFramework is the networking library used for reactive distributed communication across processes. It provides the necessary abstractions to implement client-server architectures.
  7. Use heterogeneous lookups in ordered-map/set

    master

    Heterogeneous lookups allow you to perform find or erase operations using a type different from the Key type, provided the types are hashable and comparable.

    To enable this, the KeyEqual type must have a using is_transparent = void; declaration. You can use std::equal_to<> to achieve this automatically, or define a custom comparator class.

    Both the Hash and KeyEqual functions must be implemented to handle the different types used in the lookup.

    struct equal_employee {
        using is_transparent = void;
        
        bool operator()(const employee& empl, int empl_id) const {
            return empl.m_id == empl_id;
        }
        // ... other overloads
    };
    
    // Usage with custom comparator
    tsl::ordered_map<employee, int, hash_employee, equal_employee> map2;
    map2.insert({employee(4, "Johnny Doe"), 2004});
    auto it = map2.find(4); // Works using int
  8. Use RdGen to generate language stubs

    master
    The RdGen (RD Generator) is a tool that generates stub classes in Kotlin, C#, or C++ based on models defined using a Kotlin DSL. This allows you to define your communication protocol once and use type-safe stubs in multiple languages.
  9. String view literal operators `sv` and `_sv`

    master

    To create a string_view from a literal string, the library provides two types of literal operators:

    1. sv: The standard-like literal operator. Note that Clang compilers may not allow this under C++11. Enable via -Dnssv_CONFIG_STD_SV_OPERATOR=1.
    2. _sv: A user-defined literal operator provided to ensure compatibility even when sv is restricted. This is enabled by default.

    These operators are located in the nonstd::literals::string_view_literals namespace. You can access them by using:

    • using namespace nonstd::literals;
    • using namespace nonstd::string_view_literals;
    • using namespace nonstd::literals::string_view_literals;
  10. Use functional-style extensions with tl::optional

    master

    The tl::optional library is a single-header implementation of std::optional that provides monadic/functional-style extensions. These utilities allow you to chain computations that may or may not produce a value without manual empty-checking (e.g., if (!opt) return std::nullopt;).

    Instead of nested conditional checks, you can use .and_then() for operations that return an optional and .map() for operations that return a direct value.

    gl::optional<image> get_cute_cat (const image& img) {
        return crop_to_cat(img)
               .and_then(add_bow_tie)
               .and_then(make_eyes_sparkle)
               .map(make_smaller)
               .map(add_rainbow);
    }
  11. Requirements for MPark.Variant

    master

    MPark.Variant requires a standard conformant C++11 compiler. It is continuously tested against various versions of GCC, Clang (including Xcode), and MSVC (Visual Studio 2015/2017).

    Important Notes:

    • GCC 4.8/4.9: constexpr support is unavailable for visit and relational operators.
    • libc++ tests: Enabling libc++ std::variant tests requires -std=c++17 support.
  12. Use Lifetimes for single-process reactive programming

    master
    The Lifetimes library is the JetBrains Core library used for graceful disposal, concurrency, and reactive programming within a single process. It is a foundational component for managing object lifecycles and asynchronous flows.