{"id":37736551,"url":"https://github.com/emilianobilli/libchannel","last_synced_at":"2026-01-16T14:01:00.988Z","repository":{"id":181018325,"uuid":"663565723","full_name":"emilianobilli/libchannel","owner":"emilianobilli","description":"Golang style channels in C","archived":false,"fork":false,"pushed_at":"2023-07-19T17:54:49.000Z","size":1924,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-19T19:56:58.075Z","etag":null,"topics":["c","golang-channels","library"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emilianobilli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-07-07T15:35:55.000Z","updated_at":"2024-09-12T23:17:36.000Z","dependencies_parsed_at":"2023-07-13T18:37:34.408Z","dependency_job_id":null,"html_url":"https://github.com/emilianobilli/libchannel","commit_stats":null,"previous_names":["emilianobilli/libchannel"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/emilianobilli/libchannel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilianobilli%2Flibchannel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilianobilli%2Flibchannel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilianobilli%2Flibchannel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilianobilli%2Flibchannel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emilianobilli","download_url":"https://codeload.github.com/emilianobilli/libchannel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilianobilli%2Flibchannel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479074,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","golang-channels","library"],"created_at":"2026-01-16T14:00:59.914Z","updated_at":"2026-01-16T14:01:00.971Z","avatar_url":"https://github.com/emilianobilli.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Introduction to Go-style Channels in C. libchannel\n\nGo-style channels are a powerful and flexible synchronization mechanism built into the Go programming language. They allow multiple goroutines (Go's equivalent to threads) to communicate and synchronize their execution. A goroutine can send a value into a channel and another goroutine can receive that value from the other end of the channel. This channel-based communication enables goroutines to work together to complete tasks, and it is one of the reasons why Go is known for its simplicity in handling concurrency.\n\nInspired by this, the library we are discussing brings similar channel-style mechanisms to the C programming language. This library provides a Go-like way to communicate and synchronize between threads in a C program. It's particularly suited for programs where many threads need to interact or synchronize their work in a controlled way.\n\nHere are some key concepts:\n\n- Channel: In Go, a channel is a communication medium that allows one goroutine to send values to another goroutine. In this C library, a similar concept is used. A channel is a medium through which different threads can send and receive values. Channels can be used to safely pass data between threads.\n\n- Select: In Go, the select statement is used to choose from multiple send/receive channel operations. It blocks until one of the operations is ready, and if multiple are ready at the same time, it randomly selects one. In this C library, a similar mechanism exists where a thread can wait on multiple channel operations and proceed when one is ready.\n\n- Goroutine: While C does not have direct support for goroutines, the functionality of goroutines can be approximated with threads. \n\nThis library is not a direct clone of Go's concurrency model but it brings many of its benefits to C. It enables C programs to leverage the benefits of Go-style channels, and provides a model for structuring programs that is similar to what you might find in Go.\n\n## Create a Channel\n\nIn Go, creating a channel is as simple as using the make built-in function. In our C library, we have a similar function make_chan(size_t len) to create a channel.\n\nHere is how you can use it:\n\n```\nint chan_descriptor = make_chan(10);\n```\n\nThis function takes one argument which is the size of the channel's buffer, len. In this case, the size of the channel's buffer is 10. The function returns an integer which acts as a descriptor for the created channel.\n\n\n## The any_t Structure\n\nThe any_t structure is a way to store various types of data in a type-safe way. This is done through the use of a union, which can store different types of data in the same memory space. The actual type of the data is tracked using an int field named type.\n\nHere is the any_t structure definition:\n\n```\n#define VAR_INT8         0x00\n#define VAR_INT16        0x01\n#define VAR_INT32        0x02\n#define VAR_INT64        0x03\n#define VAR_FLOAT        0x04\n#define VAR_DOUBLE       0x05\n#define VAR_POINTER      0x06\n\ntypedef struct {\n    int type;\n    union {\n        int32_t int32_val;\n        int64_t int64_val;\n        int16_t int16_val;\n        int8_t  int8_val;\n        float   float_val;\n        double  double_val;\n        void    *pointer_val;\n    } value;\n} any_t;\n```\n\n### The any_t structure has two main components:\n\n1. type: An integer that represents the type of the data stored in the value field. It can have one of the following values:\n\n- VAR_INT8: Indicates that value holds an 8-bit integer.\n- VAR_INT16: Indicates that value holds a 16-bit integer.\n- VAR_INT32: Indicates that value holds a 32-bit integer.\n- VAR_INT64: Indicates that value holds a 64-bit integer.\n- VAR_FLOAT: Indicates that value holds a single-precision floating-point number.\n- VAR_DOUBLE: Indicates that value holds a double-precision floating-point number.\n- VAR_POINTER: Indicates that value holds a pointer.\n\n2. value: A union that can hold different types of data. The actual type of data it holds is specified by the type field.\n\nHere's an example of how to use any_t to store a 32-bit integer:\n\n```\nany_t my_var;\nmy_var.type = VAR_INT32;\nmy_var.value.int32_val = 12345;\n```\n\nAnd here's an example of how to use any_t to store a pointer:\n\n```\nany_t my_var;\nmy_var.type = VAR_POINTER;\nmy_var.value.pointer_val = \u0026some_variable;\n```\n\nWhen retrieving the data from an `any_t` variable, make sure to use the correct field in the `value` union, as indicated by the type field:\n\n```\nif (my_var.type == VAR_INT32) {\n    int32_t my_int = my_var.value.int32_val;\n    // Use my_int\n} else if (my_var.type == VAR_POINTER) {\n    void *my_pointer = my_var.value.pointer_val;\n    // Use my_pointer\n}\n```\n\n\n## Using the select_chan Function\n\nThe select_chan function is used to concurrently select and perform operations on multiple channels. This function takes three arguments:\n\n```\nint select_chan(select_set_t *set, size_t n, int should_block);\n```\n\n1. An array of select_set_t structures, where each structure represents an operation (send or receive) on a specific channel.\n2. The size of the array (i.e., the number of operations to perform).\n3. A third argument that indicates whether the function should block if none of the operations can be immediately performed.\n\n### Here is an example of how to use select_chan:\n\n```\nany_t v;\nint a = make_chan(1);\nint b = make_chan(5);\n\n/* ... create pthreads to send values to the channels */\n\nfor (;;) {\n    int n;\n    select_set_t op[] = {\n        {a, OP_RECV, NULL, \u0026v},  \n        {b, OP_RECV, NULL, \u0026v}\n    };\n    n = select_chan(op, 2, SELECT_BLOCK);\n    if ( n == a ) {\n        // Received from a.\n    } else if (n == b) {\n        // Received from b.\n    }\n}\n```\n\nIn this example, select_chan will attempt to receive data from channels a and b. The function will block if there is no data available for receiving on any of the channels. When data is received on one of the channels, the function will store the data in the variable v.\n\n### The select_set_t Structure\n\n```\ntypedef struct {\n    int cd;\n    int op_type;\n    any_t *send;\n    any_t *recv;\n} select_set_t;\n```\n\nThe select_set_t structure is used to specify an operation on a specific channel. This structure has four fields:\n\n- cd: The descriptor of the channel on which the operation will be performed.\n- op_type: The type of operation to perform. Can be OP_SEND to send data or OP_RECV to receive data.\n- send: A pointer to the data to send. This field is ignored if op_type is OP_RECV.\n- recv: A pointer to a location to store received data. This field is ignored if op_type is OP_SEND.\n  \nIn the above example, both a and b are channel descriptors, OP_RECV indicates that the operation to perform is a receive, and \u0026v is a pointer to a location to store received data.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femilianobilli%2Flibchannel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femilianobilli%2Flibchannel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femilianobilli%2Flibchannel/lists"}