[{"data":1,"prerenderedAt":9089},["ShallowReactive",2],{"content":3,"blog-post-/blog/iceoryx2-0-6-release":8195},[4,1298,2206,2656,3226,3609,5041,6174,6823,7200,7939],{"id":5,"title":6,"author":7,"body":8,"date":1285,"description":1286,"extension":1287,"featured":1288,"image":1289,"meta":1290,"navigation":239,"path":1291,"seo":1292,"stem":1293,"tags":1294,"__hash__":1297},"blog/blog/advanced-messaging-patterns-blackboard.md","Advanced Messaging Patterns - Blackboard","Christian Eltzschig",{"type":9,"value":10,"toc":1274},"minimark",[11,15,19,39,62,65,68,76,82,85,104,107,112,117,120,123,126,130,133,136,139,143,146,162,165,168,177,350,358,361,369,374,377,380,602,605,608,701,704,786,790,803,806,809,1004,1007,1247,1251,1256,1267,1270],[12,13,6],"h1",{"id":14},"advanced-messaging-patterns-blackboard",[16,17,18],"p",{},"Christian Eltzschig - 12/04/2025",[20,21,22,32],"ul",{},[23,24,25],"li",{},[26,27,31],"a",{"href":28,"rel":29},"https://www.reddit.com/r/programming/comments/1jxo0gz/advanced_messaging_patterns_blackboard_for/",[30],"nofollow","Discuss on Reddit",[23,33,34],{},[26,35,38],{"href":36,"rel":37},"https://news.ycombinator.com/item?id=43666867",[30],"Discuss on Hacker News",[20,40,41,48,55],{},[23,42,43],{},[26,44,47],{"href":45,"rel":46},"https://github.com/eclipse-iceoryx/iceoryx2",[30],"Project iceoryx2 on GitHub",[23,49,50],{},[26,51,54],{"href":52,"rel":53},"https://github.com/ekxide/rmw_iceoryx2",[30],"Project iceoryx2 RMW for ROS on GitHub",[23,56,57],{},[26,58,61],{"href":59,"rel":60},"https://crates.io/crates/iceoryx2",[30],"Project on crates.io",[16,63,64],{},"Our zero-copy communication library iceoryx2 already provides several\nmessaging patterns that are well-suited for common use cases. For example,\npublish-subscribe is ideal for distributing sensor data to multiple consumers,\nrequest-response can be used to send commands—such as instructing a robot\nto move—and to receive a reply once the action is completed, and\nevent messaging is perfect for waking up another process based on\nspecific, user-defined events. A typical example: a robot searches for an object\nand sends a signal to another process once it has been found.",[16,66,67],{},"However, even these flexible messaging patterns, despite being zero-copy,\ncan reach their limits in certain inter-process communication scenarios.",[16,69,70,71,75],{},"In this article, we discuss two such use cases and introduce a new messaging\npattern called ",[72,73,74],"strong",{},"blackboard",", which has completed the design phase and will\nbe implemented in Q2 2025 in iceoryx2.",[16,77,78,79,81],{},"The ",[72,80,74],{}," messaging pattern is based on a key-value store. All keys have\nthe same shared-memory-compatible type, like a fixed-size string or an integer,\nand every value can have a different shared-memory-compatible type.",[16,83,84],{},"The pattern shines when:",[20,86,87,90,101],{},[23,88,89],{},"there is a large number of readers,",[23,91,92,93],{},"the update frequency is either low\n",[20,94,95,98],{},[23,96,97],{},"or only a few values are updated at a high frequency,",[23,99,100],{},"or individual consumers are only interested in a small subset of key-value\npairs,",[23,102,103],{},"and the readers do not require a history or previous values.",[16,105,106],{},"In network protocols, such a messaging pattern would be hard to realize, but\nwhen shared memory is available, it feels quite natural to implement such a\nconcept.",[108,109,111],"h2",{"id":110},"examples","Examples",[113,114,116],"h3",{"id":115},"the-settings-daemon-for-an-embedded-device","The Settings Daemon for an Embedded Device",[16,118,119],{},"One example comes from embedded devices. Assume you have an autonomous\nmachine like a self-driving car. It might run tens or hundreds of processes\nthat communicate with each other and depend on machine-specific configurations.",[16,121,122],{},"These configurations might even change at runtime. For instance, if a sensor\nfails or the environment changes, such as reducing maximum speed when sensor\nfunctionality is degraded (e.g., driving into the sunset after rain on a wet\nroad).",[16,124,125],{},"Again, many processes need access to a global configuration, and one\nprocess oversees and updates it as needed.",[113,127,129],{"id":128},"the-strategy-game","The Strategy Game",[16,131,132],{},"Assume you want to create a strategy game using multiple processes.\nYou have one process that renders the game and handles user interactions.\nAnother process handles the background simulation - determining where NPCs are,\nhow units behave when given orders, and so on. Additionally, there may be\nseparate processes that provide small AIs to control local behavior - such as\ndeciding what a unit should do when under fire in a specific location.",[16,134,135],{},"All these processes need to be aware of the overall game state, which is managed\nby the background simulation. The renderer needs to know object positions,\nand the AI processes need to understand their local environment.",[16,137,138],{},"In the end, multiple processes need access to the shared game state,\nwhich is updated by a single process every iteration.",[108,140,142],{"id":141},"problem-with-publish-subscribe","Problem with Publish-Subscribe",[16,144,145],{},"When using publish-subscribe in iceoryx2, the service guarantees that it can\nalways operate and never runs out of payload memory by pre-allocating sufficient\nmemory. The more subscribers, the\nlarger their buffer sizes or history requirements, the more memory iceoryx2\nmust allocate upfront.",[16,147,148,149,153,154,157,158,161],{},"This can significantly increase memory usage, as iceoryx2 must assume worst-case\nscenarios. For example, if you have ",[150,151,152],"code",{},"N"," subscribers and each holds onto a\ndifferent sample indefinitely, and each has a buffer size of ",[150,155,156],{},"B",",\nthen every publisher data segment must allocate at least ",[150,159,160],{},"N * B"," payload samples.",[16,163,164],{},"In cases like the strategy game or the settings daemon, with many readers\n(hundreds or thousands) and large global state (e.g., 1MB), iceoryx2 might\nrequire 1GB of pre-allocated memory to support the worst case.",[16,166,167],{},"Another issue arises when delivering data to many endpoints. Even with zero-copy,\nan 8-byte offset must be delivered. This is usually done by iterating an internal\nlist and pushing the offset into each subscriber’s internal queue.\nWith more subscribers, latency increases.",[16,169,170,171,176],{},"A quick measurement using the\n",[26,172,175],{"href":173,"rel":174},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/benchmarks",[30],"iceoryx2 benchmarks","\nreveals:",[178,179,184],"pre",{"className":180,"code":181,"language":182,"meta":183,"style":183},"language-sh shiki shiki-themes github-light github-dark","cargo run --bin benchmark-publish-subscribe --release -- \\\n    --bench-all --number-of-additional-subscribers 0\n# latency: 90ns\n\ncargo run --bin benchmark-publish-subscribe --release -- \\\n    --bench-all --number-of-additional-subscribers 10\n# latency: 400ns\n\ncargo run --bin benchmark-publish-subscribe --release -- \\\n    --bench-all --number-of-additional-subscribers 100\n# latency: 3400ns\n\ncargo run --bin benchmark-publish-subscribe --release -- \\\n    --bench-all --number-of-additional-subscribers 200\n# latency: 7400ns\n","sh","",[150,185,186,215,227,234,241,258,268,274,279,296,306,312,317,334,344],{"__ignoreMap":183},[187,188,191,195,199,203,206,209,212],"span",{"class":189,"line":190},"line",1,[187,192,194],{"class":193},"sScJk","cargo",[187,196,198],{"class":197},"sZZnC"," run",[187,200,202],{"class":201},"sj4cs"," --bin",[187,204,205],{"class":197}," benchmark-publish-subscribe",[187,207,208],{"class":201}," --release",[187,210,211],{"class":201}," --",[187,213,214],{"class":201}," \\\n",[187,216,218,221,224],{"class":189,"line":217},2,[187,219,220],{"class":201},"    --bench-all",[187,222,223],{"class":201}," --number-of-additional-subscribers",[187,225,226],{"class":201}," 0\n",[187,228,230],{"class":189,"line":229},3,[187,231,233],{"class":232},"sJ8bj","# latency: 90ns\n",[187,235,237],{"class":189,"line":236},4,[187,238,240],{"emptyLinePlaceholder":239},true,"\n",[187,242,244,246,248,250,252,254,256],{"class":189,"line":243},5,[187,245,194],{"class":193},[187,247,198],{"class":197},[187,249,202],{"class":201},[187,251,205],{"class":197},[187,253,208],{"class":201},[187,255,211],{"class":201},[187,257,214],{"class":201},[187,259,261,263,265],{"class":189,"line":260},6,[187,262,220],{"class":201},[187,264,223],{"class":201},[187,266,267],{"class":201}," 10\n",[187,269,271],{"class":189,"line":270},7,[187,272,273],{"class":232},"# latency: 400ns\n",[187,275,277],{"class":189,"line":276},8,[187,278,240],{"emptyLinePlaceholder":239},[187,280,282,284,286,288,290,292,294],{"class":189,"line":281},9,[187,283,194],{"class":193},[187,285,198],{"class":197},[187,287,202],{"class":201},[187,289,205],{"class":197},[187,291,208],{"class":201},[187,293,211],{"class":201},[187,295,214],{"class":201},[187,297,299,301,303],{"class":189,"line":298},10,[187,300,220],{"class":201},[187,302,223],{"class":201},[187,304,305],{"class":201}," 100\n",[187,307,309],{"class":189,"line":308},11,[187,310,311],{"class":232},"# latency: 3400ns\n",[187,313,315],{"class":189,"line":314},12,[187,316,240],{"emptyLinePlaceholder":239},[187,318,320,322,324,326,328,330,332],{"class":189,"line":319},13,[187,321,194],{"class":193},[187,323,198],{"class":197},[187,325,202],{"class":201},[187,327,205],{"class":197},[187,329,208],{"class":201},[187,331,211],{"class":201},[187,333,214],{"class":201},[187,335,337,339,341],{"class":189,"line":336},14,[187,338,220],{"class":201},[187,340,223],{"class":201},[187,342,343],{"class":201}," 200\n",[187,345,347],{"class":189,"line":346},15,[187,348,349],{"class":232},"# latency: 7400ns\n",[16,351,352,353],{},"Compared to network protocols, performance is still significantly better.\nFor instance, the best solutions for single back-and-forth communication\nshow a latency of ~5000ns. See:\n",[26,354,357],{"href":355,"rel":356},"https://arxiv.org/pdf/2303.09419",[30],"A Performance Study on the Throughput and Latency of Zenoh, MQTT, Kafka, and DDS",[16,359,360],{},"Nevertheless, two key questions remain:",[20,362,363,366],{},[23,364,365],{},"Can we reduce memory usage and make it independent of the number of\nconsumers/subscribers and their configuration?",[23,367,368],{},"Can we reduce latency and make it independent of the number of\nconsumers/subscribers and their configuration?",[16,370,371],{},[72,372,373],{},"The solution is the blackboard messaging pattern!",[108,375,376],{"id":74},"Blackboard",[16,378,379],{},"A service using the blackboard messaging pattern can be created like any other\nservice in iceoryx2:",[178,381,385],{"className":382,"code":383,"language":384,"meta":183,"style":183},"language-rust shiki shiki-themes github-light github-dark","const KEY_VALUE_1: u64 = 1;\nconst KEY_VALUE_2: u64 = 2;\n\nlet blackboard_service = node\n    .service_builder(&\"My Service Name\".try_into()?)\n    // Creates a blackboard service with u64 as key type.\n    // Any shared-memory compatible type can be used.\n    .blackboard::\u003Cu64>()\n    // Adds a key-value pair for KEY_VALUE_1 with SomeType as value type\n    .add::\u003CSomeType>(KEY_VALUE_1, SomeType::new(123))\n    // Adds a key-value pair for KEY_VALUE_2 with AnotherType as value type\n    .add::\u003CAnotherType>(KEY_VALUE_2, AnotherType::new(456))\n    .create()?;\n","rust",[150,386,387,412,430,434,448,480,485,490,508,513,551,556,589],{"__ignoreMap":183},[187,388,389,393,396,399,402,405,408],{"class":189,"line":190},[187,390,392],{"class":391},"szBVR","const",[187,394,395],{"class":201}," KEY_VALUE_1",[187,397,398],{"class":391},":",[187,400,401],{"class":193}," u64",[187,403,404],{"class":391}," =",[187,406,407],{"class":201}," 1",[187,409,411],{"class":410},"sVt8B",";\n",[187,413,414,416,419,421,423,425,428],{"class":189,"line":217},[187,415,392],{"class":391},[187,417,418],{"class":201}," KEY_VALUE_2",[187,420,398],{"class":391},[187,422,401],{"class":193},[187,424,404],{"class":391},[187,426,427],{"class":201}," 2",[187,429,411],{"class":410},[187,431,432],{"class":189,"line":229},[187,433,240],{"emptyLinePlaceholder":239},[187,435,436,439,442,445],{"class":189,"line":236},[187,437,438],{"class":391},"let",[187,440,441],{"class":410}," blackboard_service ",[187,443,444],{"class":391},"=",[187,446,447],{"class":410}," node\n",[187,449,450,453,456,459,462,465,468,471,474,477],{"class":189,"line":243},[187,451,452],{"class":391},"    .",[187,454,455],{"class":193},"service_builder",[187,457,458],{"class":410},"(",[187,460,461],{"class":391},"&",[187,463,464],{"class":197},"\"My Service Name\"",[187,466,467],{"class":391},".",[187,469,470],{"class":193},"try_into",[187,472,473],{"class":410},"()",[187,475,476],{"class":391},"?",[187,478,479],{"class":410},")\n",[187,481,482],{"class":189,"line":260},[187,483,484],{"class":232},"    // Creates a blackboard service with u64 as key type.\n",[187,486,487],{"class":189,"line":270},[187,488,489],{"class":232},"    // Any shared-memory compatible type can be used.\n",[187,491,492,494,496,499,502,505],{"class":189,"line":276},[187,493,452],{"class":391},[187,495,74],{"class":193},[187,497,498],{"class":391},"::",[187,500,501],{"class":410},"\u003C",[187,503,504],{"class":193},"u64",[187,506,507],{"class":410},">()\n",[187,509,510],{"class":189,"line":281},[187,511,512],{"class":232},"    // Adds a key-value pair for KEY_VALUE_1 with SomeType as value type\n",[187,514,515,517,520,522,524,527,530,533,536,538,540,543,545,548],{"class":189,"line":298},[187,516,452],{"class":391},[187,518,519],{"class":193},"add",[187,521,498],{"class":391},[187,523,501],{"class":410},[187,525,526],{"class":193},"SomeType",[187,528,529],{"class":410},">(",[187,531,532],{"class":201},"KEY_VALUE_1",[187,534,535],{"class":410},", ",[187,537,526],{"class":193},[187,539,498],{"class":391},[187,541,542],{"class":193},"new",[187,544,458],{"class":410},[187,546,547],{"class":201},"123",[187,549,550],{"class":410},"))\n",[187,552,553],{"class":189,"line":308},[187,554,555],{"class":232},"    // Adds a key-value pair for KEY_VALUE_2 with AnotherType as value type\n",[187,557,558,560,562,564,566,569,571,574,576,578,580,582,584,587],{"class":189,"line":314},[187,559,452],{"class":391},[187,561,519],{"class":193},[187,563,498],{"class":391},[187,565,501],{"class":410},[187,567,568],{"class":193},"AnotherType",[187,570,529],{"class":410},[187,572,573],{"class":201},"KEY_VALUE_2",[187,575,535],{"class":410},[187,577,568],{"class":193},[187,579,498],{"class":391},[187,581,542],{"class":193},[187,583,458],{"class":410},[187,585,586],{"class":201},"456",[187,588,550],{"class":410},[187,590,591,593,596,598,600],{"class":189,"line":319},[187,592,452],{"class":391},[187,594,595],{"class":193},"create",[187,597,473],{"class":410},[187,599,476],{"class":391},[187,601,411],{"class":410},[16,603,604],{},"Initially, the service will support a single writer, and the key-value pairs\nmust be defined at creation. Later, we plan to allow dynamic key-value\nadditions/removals, potentially from multiple writers.",[16,606,607],{},"The writer process looks like this:",[178,609,611],{"className":382,"code":610,"language":384,"meta":183,"style":183},"let writer = blackboard_service.writer_builder().create()?;\nlet entry = writer.entry::\u003CSomeType>(KEY_VALUE_1)?;\nentry.update(SomeType::new(7));\n",[150,612,613,642,676],{"__ignoreMap":183},[187,614,615,617,620,622,625,627,630,632,634,636,638,640],{"class":189,"line":190},[187,616,438],{"class":391},[187,618,619],{"class":410}," writer ",[187,621,444],{"class":391},[187,623,624],{"class":410}," blackboard_service",[187,626,467],{"class":391},[187,628,629],{"class":193},"writer_builder",[187,631,473],{"class":410},[187,633,467],{"class":391},[187,635,595],{"class":193},[187,637,473],{"class":410},[187,639,476],{"class":391},[187,641,411],{"class":410},[187,643,644,646,649,651,654,656,659,661,663,665,667,669,672,674],{"class":189,"line":217},[187,645,438],{"class":391},[187,647,648],{"class":410}," entry ",[187,650,444],{"class":391},[187,652,653],{"class":410}," writer",[187,655,467],{"class":391},[187,657,658],{"class":193},"entry",[187,660,498],{"class":391},[187,662,501],{"class":410},[187,664,526],{"class":193},[187,666,529],{"class":410},[187,668,532],{"class":201},[187,670,671],{"class":410},")",[187,673,476],{"class":391},[187,675,411],{"class":410},[187,677,678,680,682,685,687,689,691,693,695,698],{"class":189,"line":229},[187,679,658],{"class":410},[187,681,467],{"class":391},[187,683,684],{"class":193},"update",[187,686,458],{"class":410},[187,688,526],{"class":193},[187,690,498],{"class":391},[187,692,542],{"class":193},[187,694,458],{"class":410},[187,696,697],{"class":201},"7",[187,699,700],{"class":410},"));\n",[16,702,703],{},"The reader processes can look like this:",[178,705,707],{"className":382,"code":706,"language":384,"meta":183,"style":183},"let reader = blackboard_service.reader_builder().create()?;\nlet entry = reader.entry::\u003CSomeType>(KEY_VALUE_1)?;\nprintln!(\"The entry has the value {}\", *entry);\n",[150,708,709,737,768],{"__ignoreMap":183},[187,710,711,713,716,718,720,722,725,727,729,731,733,735],{"class":189,"line":190},[187,712,438],{"class":391},[187,714,715],{"class":410}," reader ",[187,717,444],{"class":391},[187,719,624],{"class":410},[187,721,467],{"class":391},[187,723,724],{"class":193},"reader_builder",[187,726,473],{"class":410},[187,728,467],{"class":391},[187,730,595],{"class":193},[187,732,473],{"class":410},[187,734,476],{"class":391},[187,736,411],{"class":410},[187,738,739,741,743,745,748,750,752,754,756,758,760,762,764,766],{"class":189,"line":217},[187,740,438],{"class":391},[187,742,648],{"class":410},[187,744,444],{"class":391},[187,746,747],{"class":410}," reader",[187,749,467],{"class":391},[187,751,658],{"class":193},[187,753,498],{"class":391},[187,755,501],{"class":410},[187,757,526],{"class":193},[187,759,529],{"class":410},[187,761,532],{"class":201},[187,763,671],{"class":410},[187,765,476],{"class":391},[187,767,411],{"class":410},[187,769,770,773,775,778,780,783],{"class":189,"line":229},[187,771,772],{"class":193},"println!",[187,774,458],{"class":410},[187,776,777],{"class":197},"\"The entry has the value {}\"",[187,779,535],{"class":410},[187,781,782],{"class":391},"*",[187,784,785],{"class":410},"entry);\n",[113,787,789],{"id":788},"notification-on-value-update","Notification on Value Update",[16,791,792,793,796,797,802],{},"If values should only be read when updated rather than using a polling loop,\nan additional wakeup mechanism is needed. iceoryx2 provides the ",[72,794,795],{},"event","\nmessaging pattern for this.\n(See the ",[26,798,801],{"href":799,"rel":800},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples",[30],"event example",").",[16,804,805],{},"The idea is to create an additional service with the same name using the\nevent pattern. Besides the writer, we create a notifier that sends a notification,\nusing the key as event ID, whenever a value is updated. On the reader side,\na listener waits for notifications and retrieves the new value when interested.",[16,807,808],{},"Add the following to the writer process:",[178,810,812],{"className":382,"code":811,"language":384,"meta":183,"style":183},"let event_service = node\n    .service_builder(&\"My Service Name\".into())\n    .event()\n    .open_or_create()?;\n\nlet notifier = event_service.notifier_builder().create()?;\n\n// Update the value first\nlet entry = writer.entry::\u003CSomeType>(KEY_VALUE_1)?;\nentry.update(SomeType::new(5912));\n\n// Notify the readers\nnotifier.notify_with_custom_event_id(EventId::new(KEY_VALUE_1 as _))?;\n",[150,813,814,825,845,854,867,871,900,904,909,939,962,966,971],{"__ignoreMap":183},[187,815,816,818,821,823],{"class":189,"line":190},[187,817,438],{"class":391},[187,819,820],{"class":410}," event_service ",[187,822,444],{"class":391},[187,824,447],{"class":410},[187,826,827,829,831,833,835,837,839,842],{"class":189,"line":217},[187,828,452],{"class":391},[187,830,455],{"class":193},[187,832,458],{"class":410},[187,834,461],{"class":391},[187,836,464],{"class":197},[187,838,467],{"class":391},[187,840,841],{"class":193},"into",[187,843,844],{"class":410},"())\n",[187,846,847,849,851],{"class":189,"line":229},[187,848,452],{"class":391},[187,850,795],{"class":193},[187,852,853],{"class":410},"()\n",[187,855,856,858,861,863,865],{"class":189,"line":236},[187,857,452],{"class":391},[187,859,860],{"class":193},"open_or_create",[187,862,473],{"class":410},[187,864,476],{"class":391},[187,866,411],{"class":410},[187,868,869],{"class":189,"line":243},[187,870,240],{"emptyLinePlaceholder":239},[187,872,873,875,878,880,883,885,888,890,892,894,896,898],{"class":189,"line":260},[187,874,438],{"class":391},[187,876,877],{"class":410}," notifier ",[187,879,444],{"class":391},[187,881,882],{"class":410}," event_service",[187,884,467],{"class":391},[187,886,887],{"class":193},"notifier_builder",[187,889,473],{"class":410},[187,891,467],{"class":391},[187,893,595],{"class":193},[187,895,473],{"class":410},[187,897,476],{"class":391},[187,899,411],{"class":410},[187,901,902],{"class":189,"line":270},[187,903,240],{"emptyLinePlaceholder":239},[187,905,906],{"class":189,"line":276},[187,907,908],{"class":232},"// Update the value first\n",[187,910,911,913,915,917,919,921,923,925,927,929,931,933,935,937],{"class":189,"line":281},[187,912,438],{"class":391},[187,914,648],{"class":410},[187,916,444],{"class":391},[187,918,653],{"class":410},[187,920,467],{"class":391},[187,922,658],{"class":193},[187,924,498],{"class":391},[187,926,501],{"class":410},[187,928,526],{"class":193},[187,930,529],{"class":410},[187,932,532],{"class":201},[187,934,671],{"class":410},[187,936,476],{"class":391},[187,938,411],{"class":410},[187,940,941,943,945,947,949,951,953,955,957,960],{"class":189,"line":298},[187,942,658],{"class":410},[187,944,467],{"class":391},[187,946,684],{"class":193},[187,948,458],{"class":410},[187,950,526],{"class":193},[187,952,498],{"class":391},[187,954,542],{"class":193},[187,956,458],{"class":410},[187,958,959],{"class":201},"5912",[187,961,700],{"class":410},[187,963,964],{"class":189,"line":308},[187,965,240],{"emptyLinePlaceholder":239},[187,967,968],{"class":189,"line":314},[187,969,970],{"class":232},"// Notify the readers\n",[187,972,973,976,978,981,983,986,988,990,992,994,997,1000,1002],{"class":189,"line":319},[187,974,975],{"class":410},"notifier",[187,977,467],{"class":391},[187,979,980],{"class":193},"notify_with_custom_event_id",[187,982,458],{"class":410},[187,984,985],{"class":193},"EventId",[187,987,498],{"class":391},[187,989,542],{"class":193},[187,991,458],{"class":410},[187,993,532],{"class":201},[187,995,996],{"class":391}," as",[187,998,999],{"class":410}," _))",[187,1001,476],{"class":391},[187,1003,411],{"class":410},[16,1005,1006],{},"The reader process adds:",[178,1008,1010],{"className":382,"code":1009,"language":384,"meta":183,"style":183},"let reader = blackboard_service.reader_builder().create()?;\nlet entry = reader.entry::\u003CSomeType>(KEY_VALUE_1)?;\n\nlet event_service = node\n    .service_builder(&\"My Service Name\".into())\n    .event()\n    .open_or_create()?;\n\nlet listener = event_service.listener_builder().create()?;\n\n// Wait for a notification or timeout\nif let Ok(Some(key)) = listener.timed_wait_one(TIMEOUT) {\n    // We are only interested in updates to KEY_VALUE_1\n    if key == KEY_VALUE_1 {\n        println!(\"Entry was updated to {}\", *entry);\n    }\n}\n",[150,1011,1012,1038,1068,1072,1082,1100,1108,1120,1124,1152,1156,1161,1198,1203,1219,1235,1241],{"__ignoreMap":183},[187,1013,1014,1016,1018,1020,1022,1024,1026,1028,1030,1032,1034,1036],{"class":189,"line":190},[187,1015,438],{"class":391},[187,1017,715],{"class":410},[187,1019,444],{"class":391},[187,1021,624],{"class":410},[187,1023,467],{"class":391},[187,1025,724],{"class":193},[187,1027,473],{"class":410},[187,1029,467],{"class":391},[187,1031,595],{"class":193},[187,1033,473],{"class":410},[187,1035,476],{"class":391},[187,1037,411],{"class":410},[187,1039,1040,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1066],{"class":189,"line":217},[187,1041,438],{"class":391},[187,1043,648],{"class":410},[187,1045,444],{"class":391},[187,1047,747],{"class":410},[187,1049,467],{"class":391},[187,1051,658],{"class":193},[187,1053,498],{"class":391},[187,1055,501],{"class":410},[187,1057,526],{"class":193},[187,1059,529],{"class":410},[187,1061,532],{"class":201},[187,1063,671],{"class":410},[187,1065,476],{"class":391},[187,1067,411],{"class":410},[187,1069,1070],{"class":189,"line":229},[187,1071,240],{"emptyLinePlaceholder":239},[187,1073,1074,1076,1078,1080],{"class":189,"line":236},[187,1075,438],{"class":391},[187,1077,820],{"class":410},[187,1079,444],{"class":391},[187,1081,447],{"class":410},[187,1083,1084,1086,1088,1090,1092,1094,1096,1098],{"class":189,"line":243},[187,1085,452],{"class":391},[187,1087,455],{"class":193},[187,1089,458],{"class":410},[187,1091,461],{"class":391},[187,1093,464],{"class":197},[187,1095,467],{"class":391},[187,1097,841],{"class":193},[187,1099,844],{"class":410},[187,1101,1102,1104,1106],{"class":189,"line":260},[187,1103,452],{"class":391},[187,1105,795],{"class":193},[187,1107,853],{"class":410},[187,1109,1110,1112,1114,1116,1118],{"class":189,"line":270},[187,1111,452],{"class":391},[187,1113,860],{"class":193},[187,1115,473],{"class":410},[187,1117,476],{"class":391},[187,1119,411],{"class":410},[187,1121,1122],{"class":189,"line":276},[187,1123,240],{"emptyLinePlaceholder":239},[187,1125,1126,1128,1131,1133,1135,1137,1140,1142,1144,1146,1148,1150],{"class":189,"line":281},[187,1127,438],{"class":391},[187,1129,1130],{"class":410}," listener ",[187,1132,444],{"class":391},[187,1134,882],{"class":410},[187,1136,467],{"class":391},[187,1138,1139],{"class":193},"listener_builder",[187,1141,473],{"class":410},[187,1143,467],{"class":391},[187,1145,595],{"class":193},[187,1147,473],{"class":410},[187,1149,476],{"class":391},[187,1151,411],{"class":410},[187,1153,1154],{"class":189,"line":298},[187,1155,240],{"emptyLinePlaceholder":239},[187,1157,1158],{"class":189,"line":308},[187,1159,1160],{"class":232},"// Wait for a notification or timeout\n",[187,1162,1163,1166,1169,1172,1174,1177,1180,1182,1185,1187,1190,1192,1195],{"class":189,"line":314},[187,1164,1165],{"class":391},"if",[187,1167,1168],{"class":391}," let",[187,1170,1171],{"class":193}," Ok",[187,1173,458],{"class":410},[187,1175,1176],{"class":193},"Some",[187,1178,1179],{"class":410},"(key)) ",[187,1181,444],{"class":391},[187,1183,1184],{"class":410}," listener",[187,1186,467],{"class":391},[187,1188,1189],{"class":193},"timed_wait_one",[187,1191,458],{"class":410},[187,1193,1194],{"class":201},"TIMEOUT",[187,1196,1197],{"class":410},") {\n",[187,1199,1200],{"class":189,"line":319},[187,1201,1202],{"class":232},"    // We are only interested in updates to KEY_VALUE_1\n",[187,1204,1205,1208,1211,1214,1216],{"class":189,"line":336},[187,1206,1207],{"class":391},"    if",[187,1209,1210],{"class":410}," key ",[187,1212,1213],{"class":391},"==",[187,1215,395],{"class":201},[187,1217,1218],{"class":410}," {\n",[187,1220,1221,1224,1226,1229,1231,1233],{"class":189,"line":346},[187,1222,1223],{"class":193},"        println!",[187,1225,458],{"class":410},[187,1227,1228],{"class":197},"\"Entry was updated to {}\"",[187,1230,535],{"class":410},[187,1232,782],{"class":391},[187,1234,785],{"class":410},[187,1236,1238],{"class":189,"line":1237},16,[187,1239,1240],{"class":410},"    }\n",[187,1242,1244],{"class":189,"line":1243},17,[187,1245,1246],{"class":410},"}\n",[108,1248,1250],{"id":1249},"conclusion","Conclusion",[16,1252,78,1253,1255],{},[72,1254,74],{}," messaging pattern is a powerful tool when:",[20,1257,1258,1261,1264],{},[23,1259,1260],{},"A large number of readers need to consume a large data structure,",[23,1262,1263],{},"But each is only interested in a small subset of the data,",[23,1265,1266],{},"And updates are infrequent.",[16,1268,1269],{},"Typical use cases include global configuration settings adjusted at runtime,\nor a global state updated regularly, where each participant is only interested\nin a small portion of it.",[1271,1272,1273],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":183,"searchDepth":217,"depth":217,"links":1275},[1276,1280,1281,1284],{"id":110,"depth":217,"text":111,"children":1277},[1278,1279],{"id":115,"depth":229,"text":116},{"id":128,"depth":229,"text":129},{"id":141,"depth":217,"text":142},{"id":74,"depth":217,"text":376,"children":1282},[1283],{"id":788,"depth":229,"text":789},{"id":1249,"depth":217,"text":1250},"2025-04-12T00:00:00.000Z","Explore the new blackboard messaging pattern in iceoryx2, a key-value store approach designed for scenarios with many readers and infrequent updates to large data structures.","md",false,null,{},"/blog/advanced-messaging-patterns-blackboard",{"title":6,"description":1286},"blog/advanced-messaging-patterns-blackboard",[1295,384,1296],"iceoryx2","messaging-patterns","TuNMcYaipCNJ_auaj96oawH-RMRAD0yDoN21cNpsBdw",{"id":1299,"title":1300,"author":7,"body":1301,"date":2197,"description":2198,"extension":1287,"featured":1288,"image":1289,"meta":2199,"navigation":239,"path":2200,"seo":2201,"stem":2202,"tags":2203,"__hash__":2205},"blog/blog/ekxides-iceoryx-deep-dive-service-attributes.md","ekxide's iceoryx2 Deep Dive - Service Attributes",{"type":9,"value":1302,"toc":2193},[1303,1306,1309,1323,1326,1329,1334,1338,1341,1344,1519,1522,1680,1683,1686,1689,1693,1696,1823,1826,1958,1961,2076,2079,2180,2184,2187,2190],[12,1304,1300],{"id":1305},"ekxides-iceoryx2-deep-dive-service-attributes",[16,1307,1308],{},"Christian Eltzschig - 15/06/2024",[20,1310,1311,1317],{},[23,1312,1313],{},[26,1314,31],{"href":1315,"rel":1316},"https://www.reddit.com/r/programming/comments/1dgmcam/ekxides_iceoryx2_deep_dive_service_attributes/",[30],[23,1318,1319],{},[26,1320,38],{"href":1321,"rel":1322},"https://news.ycombinator.com/item?id=40690963",[30],[16,1324,1325],{},"With this article, we are starting a new series where we dive deep into the current development progress of iceoryx2.\nWe'll explain the newest features, the problems they solve, and the cool new things you can build with iceoryx2.\nThis series will let you see what our open-source company, ekxide IO GmbH, is currently working on.\nIt also allows us to collect feedback from the community, plan and refine new features, and discover interesting projects using iceoryx2.",[16,1327,1328],{},"For those who are not familiar with iceoryx2: it is an open-source library that handles reliable and incredibly fast inter-process communication, suitable for applications ranging from desktops to mission-critical systems like cars or medical devices.\nSo, if you need to send data or signal events from process A to process B, iceoryx2 is your go-to library.",[16,1330,1331],{},[26,1332,45],{"href":45,"rel":1333},[30],[113,1335,1337],{"id":1336},"the-problem","The Problem",[16,1339,1340],{},"What problem does iceoryx2 solve?\nIt is a service-oriented inter-process middleware where you can create services with a name and send data or signals to other processes.",[16,1342,1343],{},"Assume you are building a robot with multiple camera sensors.\nYou may have several services producing video streams, publishing them on services like \"camera:front,\" \"camera:back,\" \"camera:left,\" and so on.\nIn iceoryx2, you could implement it like this:",[178,1345,1347],{"className":382,"code":1346,"language":384,"meta":183,"style":183},"let service = zero_copy::Service::new(ServiceName::new(\"camera:front\")?)\n    .publish_subscribe::\u003CCameraImage>()\n    .create()?;\n\nlet publisher = service.publisher().create()?;\n\nloop {\n    let sample = publisher.loan_uninit()?;\n    sample.write_payload(get_camera_image()).send()?;\n}\n",[150,1348,1349,1390,1406,1418,1422,1451,1455,1462,1486,1515],{"__ignoreMap":183},[187,1350,1351,1353,1356,1358,1361,1363,1366,1368,1370,1372,1375,1377,1379,1381,1384,1386,1388],{"class":189,"line":190},[187,1352,438],{"class":391},[187,1354,1355],{"class":410}," service ",[187,1357,444],{"class":391},[187,1359,1360],{"class":193}," zero_copy",[187,1362,498],{"class":391},[187,1364,1365],{"class":193},"Service",[187,1367,498],{"class":391},[187,1369,542],{"class":193},[187,1371,458],{"class":410},[187,1373,1374],{"class":193},"ServiceName",[187,1376,498],{"class":391},[187,1378,542],{"class":193},[187,1380,458],{"class":410},[187,1382,1383],{"class":197},"\"camera:front\"",[187,1385,671],{"class":410},[187,1387,476],{"class":391},[187,1389,479],{"class":410},[187,1391,1392,1394,1397,1399,1401,1404],{"class":189,"line":217},[187,1393,452],{"class":391},[187,1395,1396],{"class":193},"publish_subscribe",[187,1398,498],{"class":391},[187,1400,501],{"class":410},[187,1402,1403],{"class":193},"CameraImage",[187,1405,507],{"class":410},[187,1407,1408,1410,1412,1414,1416],{"class":189,"line":229},[187,1409,452],{"class":391},[187,1411,595],{"class":193},[187,1413,473],{"class":410},[187,1415,476],{"class":391},[187,1417,411],{"class":410},[187,1419,1420],{"class":189,"line":236},[187,1421,240],{"emptyLinePlaceholder":239},[187,1423,1424,1426,1429,1431,1434,1436,1439,1441,1443,1445,1447,1449],{"class":189,"line":243},[187,1425,438],{"class":391},[187,1427,1428],{"class":410}," publisher ",[187,1430,444],{"class":391},[187,1432,1433],{"class":410}," service",[187,1435,467],{"class":391},[187,1437,1438],{"class":193},"publisher",[187,1440,473],{"class":410},[187,1442,467],{"class":391},[187,1444,595],{"class":193},[187,1446,473],{"class":410},[187,1448,476],{"class":391},[187,1450,411],{"class":410},[187,1452,1453],{"class":189,"line":260},[187,1454,240],{"emptyLinePlaceholder":239},[187,1456,1457,1460],{"class":189,"line":270},[187,1458,1459],{"class":391},"loop",[187,1461,1218],{"class":410},[187,1463,1464,1467,1470,1472,1475,1477,1480,1482,1484],{"class":189,"line":276},[187,1465,1466],{"class":391},"    let",[187,1468,1469],{"class":410}," sample ",[187,1471,444],{"class":391},[187,1473,1474],{"class":410}," publisher",[187,1476,467],{"class":391},[187,1478,1479],{"class":193},"loan_uninit",[187,1481,473],{"class":410},[187,1483,476],{"class":391},[187,1485,411],{"class":410},[187,1487,1488,1491,1493,1496,1498,1501,1504,1506,1509,1511,1513],{"class":189,"line":281},[187,1489,1490],{"class":410},"    sample",[187,1492,467],{"class":391},[187,1494,1495],{"class":193},"write_payload",[187,1497,458],{"class":410},[187,1499,1500],{"class":193},"get_camera_image",[187,1502,1503],{"class":410},"())",[187,1505,467],{"class":391},[187,1507,1508],{"class":193},"send",[187,1510,473],{"class":410},[187,1512,476],{"class":391},[187,1514,411],{"class":410},[187,1516,1517],{"class":189,"line":298},[187,1518,1246],{"class":410},[16,1520,1521],{},"If you now write a process that requires a video stream to detect obstacles and perform an emergency brake if necessary, you could easily subscribe to such a service like this:",[178,1523,1525],{"className":382,"code":1524,"language":384,"meta":183,"style":183},"let service = zero_copy::Service::new(ServiceName::new(\"camera:front\")?)\n    .publish_subscribe::\u003CCameraImage>()\n    .open()?;\n\nlet subscriber = service.subscriber().create()?;\n\nloop {\n    if let Some(image) = subscriber.receive()? {\n        perform_some_processing(*image);\n    }\n}\n",[150,1526,1527,1563,1577,1590,1594,1622,1626,1632,1660,1672,1676],{"__ignoreMap":183},[187,1528,1529,1531,1533,1535,1537,1539,1541,1543,1545,1547,1549,1551,1553,1555,1557,1559,1561],{"class":189,"line":190},[187,1530,438],{"class":391},[187,1532,1355],{"class":410},[187,1534,444],{"class":391},[187,1536,1360],{"class":193},[187,1538,498],{"class":391},[187,1540,1365],{"class":193},[187,1542,498],{"class":391},[187,1544,542],{"class":193},[187,1546,458],{"class":410},[187,1548,1374],{"class":193},[187,1550,498],{"class":391},[187,1552,542],{"class":193},[187,1554,458],{"class":410},[187,1556,1383],{"class":197},[187,1558,671],{"class":410},[187,1560,476],{"class":391},[187,1562,479],{"class":410},[187,1564,1565,1567,1569,1571,1573,1575],{"class":189,"line":217},[187,1566,452],{"class":391},[187,1568,1396],{"class":193},[187,1570,498],{"class":391},[187,1572,501],{"class":410},[187,1574,1403],{"class":193},[187,1576,507],{"class":410},[187,1578,1579,1581,1584,1586,1588],{"class":189,"line":229},[187,1580,452],{"class":391},[187,1582,1583],{"class":193},"open",[187,1585,473],{"class":410},[187,1587,476],{"class":391},[187,1589,411],{"class":410},[187,1591,1592],{"class":189,"line":236},[187,1593,240],{"emptyLinePlaceholder":239},[187,1595,1596,1598,1601,1603,1605,1607,1610,1612,1614,1616,1618,1620],{"class":189,"line":243},[187,1597,438],{"class":391},[187,1599,1600],{"class":410}," subscriber ",[187,1602,444],{"class":391},[187,1604,1433],{"class":410},[187,1606,467],{"class":391},[187,1608,1609],{"class":193},"subscriber",[187,1611,473],{"class":410},[187,1613,467],{"class":391},[187,1615,595],{"class":193},[187,1617,473],{"class":410},[187,1619,476],{"class":391},[187,1621,411],{"class":410},[187,1623,1624],{"class":189,"line":260},[187,1625,240],{"emptyLinePlaceholder":239},[187,1627,1628,1630],{"class":189,"line":270},[187,1629,1459],{"class":391},[187,1631,1218],{"class":410},[187,1633,1634,1636,1638,1641,1644,1646,1649,1651,1654,1656,1658],{"class":189,"line":276},[187,1635,1207],{"class":391},[187,1637,1168],{"class":391},[187,1639,1640],{"class":193}," Some",[187,1642,1643],{"class":410},"(image) ",[187,1645,444],{"class":391},[187,1647,1648],{"class":410}," subscriber",[187,1650,467],{"class":391},[187,1652,1653],{"class":193},"receive",[187,1655,473],{"class":410},[187,1657,476],{"class":391},[187,1659,1218],{"class":410},[187,1661,1662,1665,1667,1669],{"class":189,"line":281},[187,1663,1664],{"class":193},"        perform_some_processing",[187,1666,458],{"class":410},[187,1668,782],{"class":391},[187,1670,1671],{"class":410},"image);\n",[187,1673,1674],{"class":189,"line":298},[187,1675,1240],{"class":410},[187,1677,1678],{"class":189,"line":308},[187,1679,1246],{"class":410},[16,1681,1682],{},"But what if you have another service that wants to create high-quality snapshots of the scenes the robot captures?\nIt would be advantageous if the service used a 4k camera.\nOr, if the robot is moving at high speed, it would be preferable to use only services where the camera produces images at a rate of 60 frames per second.",[16,1684,1685],{},"Where could we store this information for the consumers of the data?\nWe could add this in the header of the message, but for efficiency, this is not the best place to write this information repeatedly, especially when it never changes.",[16,1687,1688],{},"The solution is service attributes.",[113,1690,1692],{"id":1691},"service-attributes","Service Attributes",[16,1694,1695],{},"Service attributes are key-value pairs that remain constant during the service's lifetime.\nThey can be set when the service is created and can be read by any participant and during service discovery.",[178,1697,1699],{"className":382,"code":1698,"language":384,"meta":183,"style":183},"let service = zero_copy::Service::new(ServiceName::new(\"camera:front\")?)\n    .publish_subscribe::\u003CCameraImage>()\n    .create_with_attributes(\n        &AttributeSpecifier::new()\n            .define(\"camera-resolution\", \"1920x1080\")\n            .define(\"frames-per-second\", \"60\"),\n    )?;\n",[150,1700,1701,1737,1751,1761,1775,1795,1814],{"__ignoreMap":183},[187,1702,1703,1705,1707,1709,1711,1713,1715,1717,1719,1721,1723,1725,1727,1729,1731,1733,1735],{"class":189,"line":190},[187,1704,438],{"class":391},[187,1706,1355],{"class":410},[187,1708,444],{"class":391},[187,1710,1360],{"class":193},[187,1712,498],{"class":391},[187,1714,1365],{"class":193},[187,1716,498],{"class":391},[187,1718,542],{"class":193},[187,1720,458],{"class":410},[187,1722,1374],{"class":193},[187,1724,498],{"class":391},[187,1726,542],{"class":193},[187,1728,458],{"class":410},[187,1730,1383],{"class":197},[187,1732,671],{"class":410},[187,1734,476],{"class":391},[187,1736,479],{"class":410},[187,1738,1739,1741,1743,1745,1747,1749],{"class":189,"line":217},[187,1740,452],{"class":391},[187,1742,1396],{"class":193},[187,1744,498],{"class":391},[187,1746,501],{"class":410},[187,1748,1403],{"class":193},[187,1750,507],{"class":410},[187,1752,1753,1755,1758],{"class":189,"line":229},[187,1754,452],{"class":391},[187,1756,1757],{"class":193},"create_with_attributes",[187,1759,1760],{"class":410},"(\n",[187,1762,1763,1766,1769,1771,1773],{"class":189,"line":236},[187,1764,1765],{"class":391},"        &",[187,1767,1768],{"class":193},"AttributeSpecifier",[187,1770,498],{"class":391},[187,1772,542],{"class":193},[187,1774,853],{"class":410},[187,1776,1777,1780,1783,1785,1788,1790,1793],{"class":189,"line":243},[187,1778,1779],{"class":391},"            .",[187,1781,1782],{"class":193},"define",[187,1784,458],{"class":410},[187,1786,1787],{"class":197},"\"camera-resolution\"",[187,1789,535],{"class":410},[187,1791,1792],{"class":197},"\"1920x1080\"",[187,1794,479],{"class":410},[187,1796,1797,1799,1801,1803,1806,1808,1811],{"class":189,"line":260},[187,1798,1779],{"class":391},[187,1800,1782],{"class":193},[187,1802,458],{"class":410},[187,1804,1805],{"class":197},"\"frames-per-second\"",[187,1807,535],{"class":410},[187,1809,1810],{"class":197},"\"60\"",[187,1812,1813],{"class":410},"),\n",[187,1815,1816,1819,1821],{"class":189,"line":270},[187,1817,1818],{"class":410},"    )",[187,1820,476],{"class":391},[187,1822,411],{"class":410},[16,1824,1825],{},"When you perform a service discovery, you immediately see what attributes are set and can select the right service that satisfies all your requirements.\nIt also allows you to acquire additional information about the counterpart.",[178,1827,1829],{"className":382,"code":1828,"language":384,"meta":183,"style":183},"let service = zero_copy::Service::new(ServiceName::new(\"camera:front\")?)\n    .publish_subscribe::\u003CCameraImage>()\n    .open()?;\n\nfor attribute in service.attributes().iter() {\n    println!(\"{} = {}\", attribute.key(), attribute.value());\n}\n",[150,1830,1831,1867,1881,1893,1897,1925,1954],{"__ignoreMap":183},[187,1832,1833,1835,1837,1839,1841,1843,1845,1847,1849,1851,1853,1855,1857,1859,1861,1863,1865],{"class":189,"line":190},[187,1834,438],{"class":391},[187,1836,1355],{"class":410},[187,1838,444],{"class":391},[187,1840,1360],{"class":193},[187,1842,498],{"class":391},[187,1844,1365],{"class":193},[187,1846,498],{"class":391},[187,1848,542],{"class":193},[187,1850,458],{"class":410},[187,1852,1374],{"class":193},[187,1854,498],{"class":391},[187,1856,542],{"class":193},[187,1858,458],{"class":410},[187,1860,1383],{"class":197},[187,1862,671],{"class":410},[187,1864,476],{"class":391},[187,1866,479],{"class":410},[187,1868,1869,1871,1873,1875,1877,1879],{"class":189,"line":217},[187,1870,452],{"class":391},[187,1872,1396],{"class":193},[187,1874,498],{"class":391},[187,1876,501],{"class":410},[187,1878,1403],{"class":193},[187,1880,507],{"class":410},[187,1882,1883,1885,1887,1889,1891],{"class":189,"line":229},[187,1884,452],{"class":391},[187,1886,1583],{"class":193},[187,1888,473],{"class":410},[187,1890,476],{"class":391},[187,1892,411],{"class":410},[187,1894,1895],{"class":189,"line":236},[187,1896,240],{"emptyLinePlaceholder":239},[187,1898,1899,1902,1905,1908,1910,1912,1915,1917,1919,1922],{"class":189,"line":243},[187,1900,1901],{"class":391},"for",[187,1903,1904],{"class":410}," attribute ",[187,1906,1907],{"class":391},"in",[187,1909,1433],{"class":410},[187,1911,467],{"class":391},[187,1913,1914],{"class":193},"attributes",[187,1916,473],{"class":410},[187,1918,467],{"class":391},[187,1920,1921],{"class":193},"iter",[187,1923,1924],{"class":410},"() {\n",[187,1926,1927,1930,1932,1935,1938,1940,1943,1946,1948,1951],{"class":189,"line":260},[187,1928,1929],{"class":193},"    println!",[187,1931,458],{"class":410},[187,1933,1934],{"class":197},"\"{} = {}\"",[187,1936,1937],{"class":410},", attribute",[187,1939,467],{"class":391},[187,1941,1942],{"class":193},"key",[187,1944,1945],{"class":410},"(), attribute",[187,1947,467],{"class":391},[187,1949,1950],{"class":193},"value",[187,1952,1953],{"class":410},"());\n",[187,1955,1956],{"class":189,"line":270},[187,1957,1246],{"class":410},[16,1959,1960],{},"Another option is to define the service attributes as requirements.\nFor instance, it could be important that a specific key is defined without considering the value, or that a specific key-value pair is defined.\nLet's go back to our example and assume that we do not care about the camera resolution as long as it is defined as an attribute, but we need 60 frames per second to perform an emergency brake.",[178,1962,1964],{"className":382,"code":1963,"language":384,"meta":183,"style":183},"let service = zero_copy::Service::new(ServiceName::new(\"camera:front\")?)\n    .publish_subscribe::\u003CCameraImage>()\n    .open_with_attributes(\n        &AttributeVerifier::new()\n            .require_key(\"camera-resolution\")\n            .require(\"frames-per-second\", \"60\"),\n    )?;\n",[150,1965,1966,2002,2016,2025,2038,2051,2068],{"__ignoreMap":183},[187,1967,1968,1970,1972,1974,1976,1978,1980,1982,1984,1986,1988,1990,1992,1994,1996,1998,2000],{"class":189,"line":190},[187,1969,438],{"class":391},[187,1971,1355],{"class":410},[187,1973,444],{"class":391},[187,1975,1360],{"class":193},[187,1977,498],{"class":391},[187,1979,1365],{"class":193},[187,1981,498],{"class":391},[187,1983,542],{"class":193},[187,1985,458],{"class":410},[187,1987,1374],{"class":193},[187,1989,498],{"class":391},[187,1991,542],{"class":193},[187,1993,458],{"class":410},[187,1995,1383],{"class":197},[187,1997,671],{"class":410},[187,1999,476],{"class":391},[187,2001,479],{"class":410},[187,2003,2004,2006,2008,2010,2012,2014],{"class":189,"line":217},[187,2005,452],{"class":391},[187,2007,1396],{"class":193},[187,2009,498],{"class":391},[187,2011,501],{"class":410},[187,2013,1403],{"class":193},[187,2015,507],{"class":410},[187,2017,2018,2020,2023],{"class":189,"line":229},[187,2019,452],{"class":391},[187,2021,2022],{"class":193},"open_with_attributes",[187,2024,1760],{"class":410},[187,2026,2027,2029,2032,2034,2036],{"class":189,"line":236},[187,2028,1765],{"class":391},[187,2030,2031],{"class":193},"AttributeVerifier",[187,2033,498],{"class":391},[187,2035,542],{"class":193},[187,2037,853],{"class":410},[187,2039,2040,2042,2045,2047,2049],{"class":189,"line":243},[187,2041,1779],{"class":391},[187,2043,2044],{"class":193},"require_key",[187,2046,458],{"class":410},[187,2048,1787],{"class":197},[187,2050,479],{"class":410},[187,2052,2053,2055,2058,2060,2062,2064,2066],{"class":189,"line":260},[187,2054,1779],{"class":391},[187,2056,2057],{"class":193},"require",[187,2059,458],{"class":410},[187,2061,1805],{"class":197},[187,2063,535],{"class":410},[187,2065,1810],{"class":197},[187,2067,1813],{"class":410},[187,2069,2070,2072,2074],{"class":189,"line":270},[187,2071,1818],{"class":410},[187,2073,476],{"class":391},[187,2075,411],{"class":410},[16,2077,2078],{},"One of our internal iceoryx2 use cases for service attributes is gateways.\nWhen you want to forward a message from iceoryx2 via the MQTT protocol, you may want to use a different service name.\nSometimes it is even mandatory since the protocol does not support the iceoryx2 naming scheme, like Some/IP. With service attributes, we can now define the translation for the gateway directly in the service and specify that the \"camera:front\" service should map to the MQTT service \"camera/front.\"",[178,2080,2082],{"className":382,"code":2081,"language":384,"meta":183,"style":183},"let service = zero_copy::Service::new(ServiceName::new(\"camera:front\")?)\n    .publish_subscribe::\u003CCameraImage>()\n    .create_with_attributes(\n        &AttributeSpecifier::new()\n            .define(\"mqtt-service-name\", \"camera/front\"),\n    )?;\n",[150,2083,2084,2120,2134,2142,2154,2172],{"__ignoreMap":183},[187,2085,2086,2088,2090,2092,2094,2096,2098,2100,2102,2104,2106,2108,2110,2112,2114,2116,2118],{"class":189,"line":190},[187,2087,438],{"class":391},[187,2089,1355],{"class":410},[187,2091,444],{"class":391},[187,2093,1360],{"class":193},[187,2095,498],{"class":391},[187,2097,1365],{"class":193},[187,2099,498],{"class":391},[187,2101,542],{"class":193},[187,2103,458],{"class":410},[187,2105,1374],{"class":193},[187,2107,498],{"class":391},[187,2109,542],{"class":193},[187,2111,458],{"class":410},[187,2113,1383],{"class":197},[187,2115,671],{"class":410},[187,2117,476],{"class":391},[187,2119,479],{"class":410},[187,2121,2122,2124,2126,2128,2130,2132],{"class":189,"line":217},[187,2123,452],{"class":391},[187,2125,1396],{"class":193},[187,2127,498],{"class":391},[187,2129,501],{"class":410},[187,2131,1403],{"class":193},[187,2133,507],{"class":410},[187,2135,2136,2138,2140],{"class":189,"line":229},[187,2137,452],{"class":391},[187,2139,1757],{"class":193},[187,2141,1760],{"class":410},[187,2143,2144,2146,2148,2150,2152],{"class":189,"line":236},[187,2145,1765],{"class":391},[187,2147,1768],{"class":193},[187,2149,498],{"class":391},[187,2151,542],{"class":193},[187,2153,853],{"class":410},[187,2155,2156,2158,2160,2162,2165,2167,2170],{"class":189,"line":243},[187,2157,1779],{"class":391},[187,2159,1782],{"class":193},[187,2161,458],{"class":410},[187,2163,2164],{"class":197},"\"mqtt-service-name\"",[187,2166,535],{"class":410},[187,2168,2169],{"class":197},"\"camera/front\"",[187,2171,1813],{"class":410},[187,2173,2174,2176,2178],{"class":189,"line":260},[187,2175,1818],{"class":410},[187,2177,476],{"class":391},[187,2179,411],{"class":410},[12,2181,2183],{"id":2182},"whats-next","What's Next?",[16,2185,2186],{},"One of the things that are missing is a mechanism to make the attributes more scalable.\nWe need to come up with a configuration file or another innovative solution that allows us to define attributes, such as the iceoryx2 service to MQTT service mapping, in a more centralized manner rather than hardcoding them in the code.\nLet's see what we can come up with — we'll keep you posted.",[16,2188,2189],{},"Happy Hacking",[1271,2191,2192],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":183,"searchDepth":217,"depth":217,"links":2194},[2195,2196],{"id":1336,"depth":229,"text":1337},{"id":1691,"depth":229,"text":1692},"2024-06-15T00:00:00.000Z","Dive into iceoryx2's new service attributes feature, exploring how they enhance inter-process communication by adding metadata to services.",{},"/blog/ekxides-iceoryx-deep-dive-service-attributes",{"title":1300,"description":2198},"blog/ekxides-iceoryx-deep-dive-service-attributes",[1295,384,2204],"deep-dive","1b7R5BgYm-bvxMEt6Vs4AzOR7__UpASvIf_YWz2VgFs",{"id":2207,"title":2208,"author":7,"body":2209,"date":2647,"description":2648,"extension":1287,"featured":1288,"image":1289,"meta":2649,"navigation":239,"path":2650,"seo":2651,"stem":2652,"tags":2653,"__hash__":2655},"blog/blog/how-to-implement-zero-copy-communication.md","Implementing True Zero-Copy Communication with iceoryx2",{"type":9,"value":2210,"toc":2641},[2211,2214,2217,2221,2226,2229,2233,2236,2239,2242,2253,2256,2264,2268,2277,2307,2310,2330,2333,2338,2341,2380,2383,2403,2418,2423,2426,2468,2493,2499,2504,2507,2556,2587,2591,2594,2602,2605,2608,2638],[12,2212,2208],{"id":2213},"implementing-true-zero-copy-communication-with-iceoryx2",[16,2215,2216],{},"Christian Eltzschig - 14/06/2025",[113,2218,2220],{"id":2219},"what-is-iceoryx2","What Is iceoryx2",[16,2222,2223,2225],{},[72,2224,1295],{}," is a decentralized, service-based inter-process communication\n(IPC) library designed for mission-critical, high-efficiency systems. It\nachieves low latency and high throughput using a communication paradigm known\nas zero-copy communication.",[16,2227,2228],{},"In this article, we'll explore the core concept of zero-copy communication and\nwalk through how iceoryx2 implements it using a practical example from its\npublish-subscribe API.",[113,2230,2232],{"id":2231},"the-concept-of-zero-copy-communication","The Concept of Zero-Copy Communication",[16,2234,2235],{},"The principle of zero-copy communication is similar to how shared pointers or\nreferences work in programming: instead of copying data, we share access to a\nsingle memory location.",[16,2237,2238],{},"In the same spirit, zero-copy inter-process communication avoids unnecessary\ndata copies between processes. Data is produced once in a memory region that\nall endpoints can access, and a reference or offset to that memory is shared.\nThis allows all participants to read the data directly, just like sharing a\npointer to a struct on the heap - but across process boundaries.",[16,2240,2241],{},"In practice, this shared memory region could be:",[20,2243,2244,2247,2250],{},[23,2245,2246],{},"POSIX shared memory",[23,2248,2249],{},"GPU memory",[23,2251,2252],{},"Memory-mapped hardware buffers",[16,2254,2255],{},"The critical aspect: the sender writes the data directly into shared memory.\nThen, the offset or index to that data is transferred to every receiver.\nNo copies are involved after the data is created.",[2257,2258],"img",{"src":2259,"alt":2260,"className":2261},"blog-images/shared-memory-idea.png","shared-memory-idea",[2262,2263],"w-2/3","mx-auto",[113,2265,2267],{"id":2266},"hands-on-iceoryx2-in-action","Hands-On: iceoryx2 in Action",[16,2269,2270,2271,2276],{},"We’ll now walk through the\n",[26,2272,2275],{"href":2273,"rel":2274},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/publish_subscribe",[30],"iceoryx2 publish-subscribe example",",\nwhere data is sent by a publisher to multiple subscribers using zero-copy.",[20,2278,2279],{},[23,2280,2281,2284,2285],{},[72,2282,2283],{},"Deep Dive:","\nWhen the publisher is created:\n",[2286,2287,2288,2294,2301],"ol",{},[23,2289,2290,2291,467],{},"A shared memory object is created using ",[150,2292,2293],{},"shm_open",[23,2295,2296,2297,2300],{},"It is resized via ",[150,2298,2299],{},"ftruncate"," to reserve enough space.",[23,2302,2303,2304,467],{},"The segment is mapped into the process using ",[150,2305,2306],{},"mmap",[16,2308,2309],{},"Sensor APIs often provide a pointer to the latest data:",[178,2311,2313],{"className":382,"code":2312,"language":384,"meta":183,"style":183},"let data_ptr = sensor_get_next_frame();\n",[150,2314,2315],{"__ignoreMap":183},[187,2316,2317,2319,2322,2324,2327],{"class":189,"line":190},[187,2318,438],{"class":391},[187,2320,2321],{"class":410}," data_ptr ",[187,2323,444],{"class":391},[187,2325,2326],{"class":193}," sensor_get_next_frame",[187,2328,2329],{"class":410},"();\n",[16,2331,2332],{},"However, this is not zero-copy: the data resides in sensor-managed memory, and\nmust be copied into shared memory before sending. For true zero-copy, we\nneed the sensor to write directly into shared memory, provided by the\nzero-copy communication framework.",[16,2334,2335],{},[72,2336,2337],{},"1. Produce Data into Shared Memory",[16,2339,2340],{},"First, we acquire an uninitialized sample from the publisher. This is a chunk\nof memory from the publisher’s data segment, reserved for the user's payload.\nUnder the hood, an allocator manages this memory block:",[178,2342,2344],{"className":382,"code":2343,"language":384,"meta":183,"style":183},"let mut uninitialized_sample =\n    publisher.loan_slice_uninit(MAX_SIZE_OF_SENSOR_DATA_FRAME)?;\n",[150,2345,2346,2359],{"__ignoreMap":183},[187,2347,2348,2350,2353,2356],{"class":189,"line":190},[187,2349,438],{"class":391},[187,2351,2352],{"class":391}," mut",[187,2354,2355],{"class":410}," uninitialized_sample ",[187,2357,2358],{"class":391},"=\n",[187,2360,2361,2364,2366,2369,2371,2374,2376,2378],{"class":189,"line":217},[187,2362,2363],{"class":410},"    publisher",[187,2365,467],{"class":391},[187,2367,2368],{"class":193},"loan_slice_uninit",[187,2370,458],{"class":410},[187,2372,2373],{"class":201},"MAX_SIZE_OF_SENSOR_DATA_FRAME",[187,2375,671],{"class":410},[187,2377,476],{"class":391},[187,2379,411],{"class":410},[16,2381,2382],{},"Next, the sensor writes directly into this memory:",[178,2384,2386],{"className":382,"code":2385,"language":384,"meta":183,"style":183},"sensor_get_next_frame(uninitialized_sample.payload_mut());\n",[150,2387,2388],{"__ignoreMap":183},[187,2389,2390,2393,2396,2398,2401],{"class":189,"line":190},[187,2391,2392],{"class":193},"sensor_get_next_frame",[187,2394,2395],{"class":410},"(uninitialized_sample",[187,2397,467],{"class":391},[187,2399,2400],{"class":193},"payload_mut",[187,2402,1953],{"class":410},[20,2404,2405],{},[23,2406,2407,2409,2410,2413,2414,2417],{},[72,2408,2283],{},"\nIn iceoryx2 the memory of the data segment is managed by a pool allocator.\nIt partitions memory into fixed-size regions, which avoids fragmentation\nand allows predictable allocation times - essential for real-time and\nsafety-critical systems.",[2411,2412],"br",{},"The call to ",[150,2415,2416],{},"loan"," allocates a chunk of memory from this pool allocator and\nreturns it to the user.",[16,2419,2420],{},[72,2421,2422],{},"2. Send Pointer To Data",[16,2424,2425],{},"Once the data is produced, the sample is marked as initialized and published:",[178,2427,2429],{"className":382,"code":2428,"language":384,"meta":183,"style":183},"let sample = unsafe { uninitialized_sample.assume_init(); }\nsample.send()?;\n",[150,2430,2431,2453],{"__ignoreMap":183},[187,2432,2433,2435,2437,2439,2442,2445,2447,2450],{"class":189,"line":190},[187,2434,438],{"class":391},[187,2436,1469],{"class":410},[187,2438,444],{"class":391},[187,2440,2441],{"class":391}," unsafe",[187,2443,2444],{"class":410}," { uninitialized_sample",[187,2446,467],{"class":391},[187,2448,2449],{"class":193},"assume_init",[187,2451,2452],{"class":410},"(); }\n",[187,2454,2455,2458,2460,2462,2464,2466],{"class":189,"line":217},[187,2456,2457],{"class":410},"sample",[187,2459,467],{"class":391},[187,2461,1508],{"class":193},[187,2463,473],{"class":410},[187,2465,476],{"class":391},[187,2467,411],{"class":410},[20,2469,2470],{},[23,2471,2472,2474,2475,2490,2492],{},[72,2473,2283],{},"\nOnly an offset to the memory location is sent to the subscribers, not the\nactual data.\nEach process has its own virtual memory layout, so we cannot directly\nshare pointers. Instead:",[20,2476,2477,2480,2483],{},[23,2478,2479],{},"The publisher calculates an offset from the base of the shared memory segment.",[23,2481,2482],{},"The subscriber adds this offset to its local mapping of that segment.",[23,2484,2485,2486,2488],{},"A valid pointer to the received data is reconstructed from the\noffset.",[2411,2487],{},[2411,2489],{},[2411,2491],{},"To transfer the offset, an inter-process communication mechanisms like\nmessage queues, pipes, unix domain sockets, or shared memory queues can be\nused.",[2257,2494],{"src":2495,"alt":2496,"className":2497},"blog-images/offset.png","offset",[2263,2498,2263],"w-3/4",[16,2500,2501],{},[72,2502,2503],{},"3. Read Data",[16,2505,2506],{},"Upon receiving the offset, the subscriber can reconstruct a pointer and\naccess the data directly:",[178,2508,2510],{"className":382,"code":2509,"language":384,"meta":183,"style":183},"if let Some(sample) = subscriber.receive()? {\n  process_sensor_data(sample.payload());\n}\n",[150,2511,2512,2537,2552],{"__ignoreMap":183},[187,2513,2514,2516,2518,2520,2523,2525,2527,2529,2531,2533,2535],{"class":189,"line":190},[187,2515,1165],{"class":391},[187,2517,1168],{"class":391},[187,2519,1640],{"class":193},[187,2521,2522],{"class":410},"(sample) ",[187,2524,444],{"class":391},[187,2526,1648],{"class":410},[187,2528,467],{"class":391},[187,2530,1653],{"class":193},[187,2532,473],{"class":410},[187,2534,476],{"class":391},[187,2536,1218],{"class":410},[187,2538,2539,2542,2545,2547,2550],{"class":189,"line":217},[187,2540,2541],{"class":193},"  process_sensor_data",[187,2543,2544],{"class":410},"(sample",[187,2546,467],{"class":391},[187,2548,2549],{"class":193},"payload",[187,2551,1953],{"class":410},[187,2553,2554],{"class":189,"line":229},[187,2555,1246],{"class":410},[20,2557,2558],{},[23,2559,2560,2562,2563,2584,2586],{},[72,2561,2283],{},"\nBefore a subscriber can consume the received data:",[2286,2564,2565,2574,2577],{},[23,2566,2567,2568,2570,2571,2573],{},"It must map the publisher’s shared memory using ",[150,2569,2293],{}," and ",[150,2572,2306],{},".\nThis happens when the subscriber is created.",[23,2575,2576],{},"It polls for incoming offsets from the publisher. If this is not\ndesired, the subscriber can be combined with a listener port from the\nevent messaging pattern that is able to wait for incoming data.",[23,2578,2579,2580,2582],{},"On receipt, it reconstructs the pointer from the offset and reads the\ndata — no copying involved.",[2411,2581],{},[2411,2583],{},[2411,2585],{},"This mechanism ensures the subscriber can consume the data efficiently and\nwith minimal latency.",[113,2588,2590],{"id":2589},"summary","Summary",[16,2592,2593],{},"The key difference between traditional communication (e.g., sockets with\nserialization) and zero-copy inter-process communication lies in who owns and\nprovides the memory.",[20,2595,2596,2599],{},[23,2597,2598],{},"In classical inter-process communication, the user provides a buffer to the\nsystem.",[23,2600,2601],{},"In zero-copy inter-process communication, the framework provides the memory\nwhich is shared between all endpoints.",[16,2603,2604],{},"With iceoryx2, publishers produce data directly into shared memory. Subscribers\nreceive only an offset, which they resolve into local pointers.",[16,2606,2607],{},"This guarantees true zero-copy communication. No serialization, no redundant\nallocations, no data duplication - just high-performance, low-latency data\nexchange.",[20,2609,2610,2616,2623,2628,2633],{},[23,2611,2612],{},[26,2613,31],{"href":2614,"rel":2615},"https://www.reddit.com/r/programming/comments/1lb5ymp/implementing_true_zerocopy_communication_with/",[30],[23,2617,2618],{},[26,2619,2622],{"href":2620,"rel":2621},"https://programming.dev/post/32188221",[30],"Discuss on programming.dev",[23,2624,2625],{},[26,2626,47],{"href":45,"rel":2627},[30],[23,2629,2630],{},[26,2631,54],{"href":52,"rel":2632},[30],[23,2634,2635],{},[26,2636,61],{"href":59,"rel":2637},[30],[1271,2639,2640],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":183,"searchDepth":217,"depth":217,"links":2642},[2643,2644,2645,2646],{"id":2219,"depth":229,"text":2220},{"id":2231,"depth":229,"text":2232},{"id":2266,"depth":229,"text":2267},{"id":2589,"depth":229,"text":2590},"2025-06-14T00:00:00.000Z","Explore the concept of Zero-Copy Communication and how iceoryx2 implements it.",{},"/blog/how-to-implement-zero-copy-communication",{"title":2208,"description":2648},"blog/how-to-implement-zero-copy-communication",[1295,2654],"zerocopy","e38fjG50pJo6_JwY87nRAzdzfo-W_RYXlyauHUhUI2A",{"id":2657,"title":2658,"author":7,"body":2659,"date":3217,"description":3218,"extension":1287,"featured":1288,"image":1289,"meta":3219,"navigation":239,"path":3220,"seo":3221,"stem":3222,"tags":3223,"__hash__":3225},"blog/blog/iceoryx2-0-3-release.md","Announcing iceoryx2 v0.3.0",{"type":9,"value":2660,"toc":3206},[2661,2664,2667,2676,2679,2704,2708,2712,2731,2742,2746,2753,2764,2768,2787,2910,2918,2923,2926,3019,3023,3026,3046,3052,3095,3101,3148,3152,3155,3158,3161,3164,3168,3177,3181,3189,3192,3203],[12,2662,2658],{"id":2663},"announcing-iceoryx2-v030",[16,2665,2666],{},"Christian Eltzschig - 18/04/2024",[16,2668,2669,2670,2675],{},"Today, I am happy to announce ",[26,2671,2674],{"href":2672,"rel":2673},"https://github.com/eclipse-iceoryx/iceoryx2/releases/tag/v0.3.0",[30],"iceoryx2 v0.3.0",".\nThe release comes with cool new features, improved documentation and additional examples.",[16,2677,2678],{},"So here we go.",[20,2680,2681,2687,2693,2699],{},[23,2682,2683],{},[26,2684,31],{"href":2685,"rel":2686},"https://www.reddit.com/r/rust/comments/1c7709n/iceoryx2_v030_released_a_platformagnostic_and/",[30],[23,2688,2689],{},[26,2690,38],{"href":2691,"rel":2692},"https://news.ycombinator.com/item?id=40077490",[30],[23,2694,2695],{},[26,2696,2698],{"href":45,"rel":2697},[30],"Project on GitHub",[23,2700,2701],{},[26,2702,61],{"href":59,"rel":2703},[30],[108,2705,2707],{"id":2706},"features-improvements","Features & Improvements",[113,2709,2711],{"id":2710},"communication-between-docker-containers","Communication Between Docker Containers",[16,2713,2714,2715,2718,2719,2570,2721,2724,2725,2730],{},"With iceoryx2, you can establish zero-copy communication between multiple docker containers.\nSince iceoryx2 is just using shared memory and some files stored in ",[150,2716,2717],{},"/tmp/iceoryx2"," for communication, all you have to do is to share ",[150,2720,2717],{},[150,2722,2723],{},"/dev/shm"," with all your docker containers, and everything works.\nWe created a ",[26,2726,2729],{"href":2727,"rel":2728},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/examples/docker",[30],"docker example"," that explains all the little details.",[16,2732,2733,2736,2737],{},[72,2734,2735],{},"Note:"," All paths and naming schemes can be configured via a config file.\nFor more details and documentation, take a look at the ",[26,2738,2741],{"href":2739,"rel":2740},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/config",[30],"iceoryx2 default configuration",[113,2743,2745],{"id":2744},"services-without-lifetime-parameters","Services Without Lifetime Parameters",[16,2747,2748,2749,2752],{},"In v0.2, every endpoint and payload sample in iceoryx2 had generic lifetime parameters.\nThe idea was that a service is, from a high-level point of view, a factory of endpoints like publishers or subscribers.\nThose endpoints were again factories for samples.\nFor instance, a subscriber \"produces\" a sample when the call ",[150,2750,2751],{},"my_subscriber::receive()"," returns the received sample.\nUnder the hood, the service created system resources that had to live as long as any endpoints or samples were active.\nTherefore, the service must live as long as an endpoint and an endpoint at least as long as a sample.",[16,2754,2755,2756,2759,2760,2763],{},"But you run into trouble when you would like to store samples from different endpoints, with different lifetimes, in a ",[150,2757,2758],{},"Vec"," to cache them for later.\nBut thanks to ",[150,2761,2762],{},"Arc",", which allowed us to share the ownership of those resources, the problem is gone, and the API is now much easier to use.",[113,2765,2767],{"id":2766},"sending-complex-data","Sending Complex Data",[16,2769,2770,2771,2776,2777,535,2780,2782,2783,2786],{},"Usually, you want to send more complex data than just arrays of integers via shared memory.\nThis is why ",[26,2772,2775],{"href":2773,"rel":2774},"https://docs.rs/iceoryx2-bb-container/latest/iceoryx2_bb_container/",[30],"iceoryx2-bb-containers"," becomes public API with this iceoryx2 release.\nIt comes with compile-time fixed-size versions of ",[150,2778,2779],{},"Queue",[150,2781,2758],{},", and ",[150,2784,2785],{},"ByteString"," that can be used as building blocks for transmission types.",[178,2788,2790],{"className":382,"code":2789,"language":384,"meta":183,"style":183},"use iceoryx2_bb_container::{\n    byte_string::FixedSizeByteString, vec::FixedSizeVec,\n};\n\n#[derive(Debug, Default)]\n#[repr(C)]\npub struct ComplexDataType {\n    text: FixedSizeByteString\u003C8>,\n    vec_of_data: FixedSizeVec\u003Cu64, 4>,\n}\n",[150,2791,2792,2805,2828,2833,2837,2853,2863,2876,2889,2906],{"__ignoreMap":183},[187,2793,2794,2797,2800,2802],{"class":189,"line":190},[187,2795,2796],{"class":391},"use",[187,2798,2799],{"class":193}," iceoryx2_bb_container",[187,2801,498],{"class":391},[187,2803,2804],{"class":410},"{\n",[187,2806,2807,2810,2812,2815,2817,2820,2822,2825],{"class":189,"line":217},[187,2808,2809],{"class":193},"    byte_string",[187,2811,498],{"class":391},[187,2813,2814],{"class":193},"FixedSizeByteString",[187,2816,535],{"class":410},[187,2818,2819],{"class":193},"vec",[187,2821,498],{"class":391},[187,2823,2824],{"class":193},"FixedSizeVec",[187,2826,2827],{"class":410},",\n",[187,2829,2830],{"class":189,"line":229},[187,2831,2832],{"class":410},"};\n",[187,2834,2835],{"class":189,"line":236},[187,2836,240],{"emptyLinePlaceholder":239},[187,2838,2839,2842,2845,2847,2850],{"class":189,"line":243},[187,2840,2841],{"class":410},"#[derive(",[187,2843,2844],{"class":193},"Debug",[187,2846,535],{"class":410},[187,2848,2849],{"class":193},"Default",[187,2851,2852],{"class":410},")]\n",[187,2854,2855,2858,2861],{"class":189,"line":260},[187,2856,2857],{"class":410},"#[repr(",[187,2859,2860],{"class":193},"C",[187,2862,2852],{"class":410},[187,2864,2865,2868,2871,2874],{"class":189,"line":270},[187,2866,2867],{"class":391},"pub",[187,2869,2870],{"class":391}," struct",[187,2872,2873],{"class":193}," ComplexDataType",[187,2875,1218],{"class":410},[187,2877,2878,2881,2883,2886],{"class":189,"line":276},[187,2879,2880],{"class":410},"    text",[187,2882,398],{"class":391},[187,2884,2885],{"class":193}," FixedSizeByteString",[187,2887,2888],{"class":410},"\u003C8>,\n",[187,2890,2891,2894,2896,2899,2901,2903],{"class":189,"line":281},[187,2892,2893],{"class":410},"    vec_of_data",[187,2895,398],{"class":391},[187,2897,2898],{"class":193}," FixedSizeVec",[187,2900,501],{"class":410},[187,2902,504],{"class":193},[187,2904,2905],{"class":410},", 4>,\n",[187,2907,2908],{"class":189,"line":298},[187,2909,1246],{"class":410},[16,2911,2912,2913],{},"If you would like to see a complete working example, take a look at the ",[26,2914,2917],{"href":2915,"rel":2916},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/examples/complex_data_types",[30],"complex data types example",[16,2919,2920,2922],{},[72,2921,2735],{}," I know defining the capacity at compile-time is not yet perfect.\nHowever, we are working on runtime dynamic data types based on relocatable containers that will be available with an upcoming release.",[16,2924,2925],{},"Then, you can define your transmission types without any compile-time restrictions.",[178,2927,2929],{"className":382,"code":2928,"language":384,"meta":183,"style":183},"use iceoryx2_bb_container::vec::RelocatableVec;\n\n#[derive(Debug, Default)]\n#[repr(C)]\npub struct ComplexDataType {\n    some_data: RelocatableVec\u003Cu64>,\n    other_data: RelocatableVec\u003Cf32>,\n}\n",[150,2930,2931,2948,2952,2964,2972,2982,2999,3015],{"__ignoreMap":183},[187,2932,2933,2935,2937,2939,2941,2943,2946],{"class":189,"line":190},[187,2934,2796],{"class":391},[187,2936,2799],{"class":193},[187,2938,498],{"class":391},[187,2940,2819],{"class":193},[187,2942,498],{"class":391},[187,2944,2945],{"class":193},"RelocatableVec",[187,2947,411],{"class":410},[187,2949,2950],{"class":189,"line":217},[187,2951,240],{"emptyLinePlaceholder":239},[187,2953,2954,2956,2958,2960,2962],{"class":189,"line":229},[187,2955,2841],{"class":410},[187,2957,2844],{"class":193},[187,2959,535],{"class":410},[187,2961,2849],{"class":193},[187,2963,2852],{"class":410},[187,2965,2966,2968,2970],{"class":189,"line":236},[187,2967,2857],{"class":410},[187,2969,2860],{"class":193},[187,2971,2852],{"class":410},[187,2973,2974,2976,2978,2980],{"class":189,"line":243},[187,2975,2867],{"class":391},[187,2977,2870],{"class":391},[187,2979,2873],{"class":193},[187,2981,1218],{"class":410},[187,2983,2984,2987,2989,2992,2994,2996],{"class":189,"line":260},[187,2985,2986],{"class":410},"    some_data",[187,2988,398],{"class":391},[187,2990,2991],{"class":193}," RelocatableVec",[187,2993,501],{"class":410},[187,2995,504],{"class":193},[187,2997,2998],{"class":410},">,\n",[187,3000,3001,3004,3006,3008,3010,3013],{"class":189,"line":270},[187,3002,3003],{"class":410},"    other_data",[187,3005,398],{"class":391},[187,3007,2991],{"class":193},[187,3009,501],{"class":410},[187,3011,3012],{"class":193},"f32",[187,3014,2998],{"class":410},[187,3016,3017],{"class":189,"line":276},[187,3018,1246],{"class":410},[113,3020,3022],{"id":3021},"improved-event-communication","Improved Event Communication",[16,3024,3025],{},"The event messaging pattern is iceoryx2's basic building block for async operations and push notifications.\nThe new release is based on the ported C++ iceoryx1 bitset, which solves the problem of a limited queue buffer on the listener side.",[16,3027,3028,3029,3032,3033,3035,3036,3039,3040,3042,3043,3045],{},"When a ",[150,3030,3031],{},"Notifier"," sends notifications with their ",[150,3034,985],{},"s in a busy loop, the buffer is filled quickly, and other Notifiers cannot send their notifications to the ",[150,3037,3038],{},"Listener",".\nA bitset where the ",[150,3041,3031],{}," flips a bit corresponding to the ",[150,3044,985],{}," solves the issue.",[16,3047,3048,3049,3051],{},"Furthermore, we refined the API so that you can choose to take either one ",[150,3050,985],{}," after another in a loop:",[178,3053,3055],{"className":382,"code":3054,"language":384,"meta":183,"style":183},"for event_id in listener.blocking_wait_one()? {\n    println!(\"event was triggered with id: {:?}\", event_id);\n}\n",[150,3056,3057,3079,3091],{"__ignoreMap":183},[187,3058,3059,3061,3064,3066,3068,3070,3073,3075,3077],{"class":189,"line":190},[187,3060,1901],{"class":391},[187,3062,3063],{"class":410}," event_id ",[187,3065,1907],{"class":391},[187,3067,1184],{"class":410},[187,3069,467],{"class":391},[187,3071,3072],{"class":193},"blocking_wait_one",[187,3074,473],{"class":410},[187,3076,476],{"class":391},[187,3078,1218],{"class":410},[187,3080,3081,3083,3085,3088],{"class":189,"line":217},[187,3082,1929],{"class":193},[187,3084,458],{"class":410},[187,3086,3087],{"class":197},"\"event was triggered with id: {:?}\"",[187,3089,3090],{"class":410},", event_id);\n",[187,3092,3093],{"class":189,"line":229},[187,3094,1246],{"class":410},[16,3096,3097,3098,3100],{},"or to acquire all received ",[150,3099,985],{},"s at once",[178,3102,3104],{"className":382,"code":3103,"language":384,"meta":183,"style":183},"listener.blocking_wait_all(|id| {\n    println!(\"event was triggered with id: {:?}\", id);\n})?;\n",[150,3105,3106,3128,3139],{"__ignoreMap":183},[187,3107,3108,3111,3113,3116,3118,3121,3124,3126],{"class":189,"line":190},[187,3109,3110],{"class":410},"listener",[187,3112,467],{"class":391},[187,3114,3115],{"class":193},"blocking_wait_all",[187,3117,458],{"class":410},[187,3119,3120],{"class":391},"|",[187,3122,3123],{"class":410},"id",[187,3125,3120],{"class":391},[187,3127,1218],{"class":410},[187,3129,3130,3132,3134,3136],{"class":189,"line":217},[187,3131,1929],{"class":193},[187,3133,458],{"class":410},[187,3135,3087],{"class":197},[187,3137,3138],{"class":410},", id);\n",[187,3140,3141,3144,3146],{"class":189,"line":229},[187,3142,3143],{"class":410},"})",[187,3145,476],{"class":391},[187,3147,411],{"class":410},[113,3149,3151],{"id":3150},"bug-fixes","Bug Fixes",[16,3153,3154],{},"A big thanks to our first users, who started playing around with iceoryx2 and helped us refine the API and iron out the edges.",[16,3156,3157],{},"We fixed a ton of bugs!",[16,3159,3160],{},"Most bugs were connected to the decentralized nature of iceoryx2, and we encountered some races when endpoints connected and disconnected at a high frequency.\nHowever, many additional concurrent stress tests now give us the confidence that they stay fixed.",[16,3162,3163],{},"The communication mechanism did not raise bug reports, mainly because they were proven-in-use for years in iceoryx1 and were just ported to iceoryx2.",[113,3165,3167],{"id":3166},"performance-improvements","Performance Improvements",[16,3169,3170,3171,3176],{},"We took some time to improve the performance of iceoryx2 even further and realized that we hit a limit where the performance becomes very architecture/OS dependent. Look at the ",[26,3172,3175],{"href":3173,"rel":3174},"https://github.com/eclipse-iceoryx/iceoryx2/blob/main/README.md",[30],"iceoryx2 readme"," where we provide an overview of our results.",[108,3178,3180],{"id":3179},"what-comes-next","What Comes Next",[16,3182,3183,3184,467],{},"Take a look at our ",[26,3185,3188],{"href":3186,"rel":3187},"https://github.com/eclipse-iceoryx/iceoryx2/blob/main/ROADMAP.md",[30],"Roadmap",[16,3190,3191],{},"In Q2 we want to focus:",[20,3193,3194,3197,3200],{},[23,3195,3196],{},"on our first language binding to C",[23,3198,3199],{},"introduce advanced monitoring so that manual cleanups are no longer required when an application has crashed",[23,3201,3202],{},"on sending serializable structs via shared memory so that any kind of type - without restriction - can be sent",[1271,3204,3205],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":183,"searchDepth":217,"depth":217,"links":3207},[3208,3216],{"id":2706,"depth":217,"text":2707,"children":3209},[3210,3211,3212,3213,3214,3215],{"id":2710,"depth":229,"text":2711},{"id":2744,"depth":229,"text":2745},{"id":2766,"depth":229,"text":2767},{"id":3021,"depth":229,"text":3022},{"id":3150,"depth":229,"text":3151},{"id":3166,"depth":229,"text":3167},{"id":3179,"depth":217,"text":3180},"2024-04-18T00:00:00.000Z","Release announcement for iceoryx2 v0.3.0, featuring Docker container communication, improved API, and more.",{},"/blog/iceoryx2-0-3-release",{"title":2658,"description":3218},"blog/iceoryx2-0-3-release",[1295,3224],"release","Eoqeax9S6EK8pqKrIlr48aYgYgPTyz2LKL-Q7D8wluk",{"id":3227,"title":3228,"author":7,"body":3229,"date":3599,"description":3600,"extension":1287,"featured":1288,"image":1289,"meta":3601,"navigation":239,"path":3602,"seo":3603,"stem":3604,"tags":3605,"__hash__":3608},"blog/blog/iceoryx2-0-4-release.md","Announcing iceoryx2 v0.4.0",{"type":9,"value":3230,"toc":3591},[3231,3234,3237,3243,3245,3248,3252,3266,3290,3293,3363,3374,3380,3384,3387,3409,3411,3444,3446,3514,3518,3521,3535,3538,3544,3547],[12,3232,3228],{"id":3233},"announcing-iceoryx2-v040",[16,3235,3236],{},"Christian Eltzschig - 28/09/2024",[2257,3238],{"src":3239,"alt":3240,"className":3241},"blog-images/iceoryx-blog-header.png","Header",[3242,2263],"w-1/1",[108,3244,2220],{"id":2219},[16,3246,3247],{},"iceoryx2 is a service-based inter-process communication (IPC) library designed\nto make communication between processes as fast as possible - like Unix domain\nsockets or message queues, but orders of magnitude faster and easier to use.\nIt also comes with advanced features such as circular buffers, history, event\nnotifications, publish-subscribe messaging, and a decentralized architecture\nwith no need for a broker.",[108,3249,3251],{"id":3250},"release-v040","Release v0.4.0",[16,3253,3254,3255,3260,3261,467],{},"With today's\n",[26,3256,3259],{"href":3257,"rel":3258},"https://github.com/eclipse-iceoryx/iceoryx2/releases/tag/v0.4.0",[30],"iceoryx2 v0.4.0 release",",\nwe've achieved many of our milestones and are now close to feature parity with\nits predecessor, the trusty old\n",[26,3262,3265],{"href":3263,"rel":3264},"https://github.com/eclipse-iceoryx/iceoryx",[30],"iceoryx",[20,3267,3268,3274,3280,3285],{},[23,3269,3270],{},[26,3271,31],{"href":3272,"rel":3273},"https://www.reddit.com/r/programming/comments/1fri9v0/announcing_iceoryx2_v04_incredibly_fast/",[30],[23,3275,3276],{},[26,3277,38],{"href":3278,"rel":3279},"https://news.ycombinator.com/item?id=41681344",[30],[23,3281,3282],{},[26,3283,2698],{"href":45,"rel":3284},[30],[23,3286,3287],{},[26,3288,61],{"href":59,"rel":3289},[30],[16,3291,3292],{},"If you're wondering why you should choose iceoryx2 over iceoryx, here are some\nof its next-gen features:",[20,3294,3295,3298,3305,3308,3315,3318,3321,3328,3346],{},[23,3296,3297],{},"No more need for a central daemon like RouDi.",[23,3299,3300,3301,3304],{},"It's up to ",[72,3302,3303],{},"10 times faster"," thanks to a new, more efficient architecture.",[23,3306,3307],{},"More dynamic than ever—no more compile-time memory pool configuration.",[23,3309,3310,3311,3314],{},"Advanced ",[72,3312,3313],{},"Quality of Service"," (QoS) settings.",[23,3316,3317],{},"Extremely modular: every aspect of iceoryx2 can be customized, allowing future\nsupport for GPUs, FPGAs, and more.",[23,3319,3320],{},"Completely decentralized and even more robust.",[23,3322,3323,3324,3327],{},"A restructured API and resource management system that enables a\n",[72,3325,3326],{},"zero-trust policy"," for true zero-copy communication in the future.",[23,3329,3330,3331,3334,3335,2570,3338,3341,3342,3345],{},"Language bindings for ",[72,3332,3333],{},"C and C++"," with ",[72,3336,3337],{},"CMake",[72,3339,3340],{},"Bazel"," support\nright out of the box. ",[72,3343,3344],{},"Python"," and other languages are coming soon.",[23,3347,3348,3349,3352,3353,535,3356,535,3359,3362],{},"Upcoming ",[72,3350,3351],{},"gateways"," to enable network communication via protocols like\n",[72,3354,3355],{},"zenoh",[72,3357,3358],{},"DDS",[72,3360,3361],{},"MQTT",", and more.",[16,3364,3365,3366,3369,3370,3373],{},"With this new release, we're faster than ever. On some platforms,\n",[72,3367,3368],{},"latency is even under 100ns","! Be sure to check out our\n",[26,3371,175],{"href":173,"rel":3372},[30],"\nand try them out on your platform.",[2257,3375],{"src":3376,"alt":3377,"className":3378},"blog-images/benchmark_progression.png","benchmark",[3379,2263],"w-7/8",[113,3381,3383],{"id":3382},"highlights","Highlights",[16,3385,3386],{},"Here are some of the feature highlights in v0.4.0:",[20,3388,3389],{},[23,3390,3391,3394,3395,3398,3399],{},[72,3392,3393],{},"C and C++ language bindings",": We've added a range of new\n",[26,3396,110],{"href":799,"rel":3397},[30],"\nto help you get started with the supported languages.",[20,3400,3401],{},[23,3402,3403,3404,3408],{},"Plus, there's a shiny new website:\n",[26,3405,3406],{"href":3406,"rel":3407},"https://iceoryx2.readthedocs.io",[30],",\nwhere we're building a detailed introduction to inter-process\ncommunication, true zero-copy, and iceoryx2. Whether you're just getting\nstarted or looking to fine-tune every feature to your needs, it's all in\none place.",[2411,3410],{},[20,3412,3413],{},[23,3414,3415,3418,3419],{},[72,3416,3417],{},"New build systems",": C and C++ bindings come with support for:",[20,3420,3421,3428],{},[23,3422,3423,3425,3426],{},[72,3424,3340],{}," & ",[72,3427,3337],{},[23,3429,3430,3433,3434,3437,3438,3443],{},[72,3431,3432],{},"colcon",": We're working on ",[150,3435,3436],{},"iceoryx2_rmw",", which will be unveiled at\n",[26,3439,3442],{"href":3440,"rel":3441},"https://roscon.ros.org/2024/",[30],"ROSCon 2024"," during Mathias'\ntalk: \"iceoryx2: A Journey to Becoming a First-Class RMW Alternative.\"",[2411,3445],{},[20,3447,3448,3454,3466,3472,3478,3490,3496,3502,3508],{},[23,3449,3450,3453],{},[72,3451,3452],{},"iceoryx2 nodes",": Nodes are the central entity handling all process-local\nresources, such as ports, and are key to monitoring other processes and\nnodes. If a process crashes, the others will clean up resources as soon as\nthe issue is detected.",[23,3455,3456,3459,3460,3465],{},[72,3457,3458],{},"Command-line debugging and introspection",": Meet\n",[26,3461,3464],{"href":3462,"rel":3463},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/iceoryx2-cli",[30],"iox2",".\nIf you want to see which services or nodes are running—or if you're curious\nabout the details of a service or process—this is your go-to tool.",[23,3467,3468,3471],{},[72,3469,3470],{},"Runtime-sized services",": We've overcome the compile-time memory\nconfiguration limitation of iceoryx1. If you want to send a dynamic-sized\ntyped array (like a Rust slice), you can set up the service and publisher\nwith a runtime worst-case size. If that's insufficient, you can create a\nnew publisher with a larger array size.",[23,3473,3474,3477],{},[72,3475,3476],{},"Advanced service and port configurations",": For specialized use cases,\nlike SIMD or FPGA, you can define custom alignments for your service's\npayload.",[23,3479,3480,3483,3484,3489],{},[72,3481,3482],{},"User-defined service attributes",": You can now set custom key-value pairs\nto tag services with additional properties. Check out the\n",[26,3485,3488],{"href":3486,"rel":3487},"https://ekxide.io/blog/ekxides-iceoryx-deep-dive-service-attributes/",[30],"iceoryx2 Deep Dive - Service Attributes","\nfor more details.",[23,3491,3492,3495],{},[72,3493,3494],{},"iceoryx2 Domains",": Separate multiple processes into domains, ensuring\nthey don't interfere with one another.",[23,3497,3498,3501],{},[72,3499,3500],{},"Custom User Header",": There's an interface for defining a custom header\nthat is sent with every sample.",[23,3503,3504,3507],{},[72,3505,3506],{},"32-bit support",": iceoryx2 now runs on 32-bit machines, and long-term, we\naim to support mixed-mode zero-copy communication between 32-bit and\n64-bit processes.",[23,3509,3510,3513],{},[72,3511,3512],{},"Placement new for iceoryx2-bb-containers",": Since iceoryx2 can handle\ngigabytes of data, we provide a mechanism to loan memory and perform\nin-place initialization—something akin to C++'s placement new.",[108,3515,3517],{"id":3516},"sneak-peak-mission-control","Sneak Peak: Mission Control",[16,3519,3520],{},"Our upcoming Mission Control Center will provide deep introspection and\ndebugging for your iceoryx2 system. You’ll be able to monitor the CPU, memory,\nand I/O load of every process. You can also view the frequency and content of\nmessage samples, inspect individual nodes with their running services, and\nvisualize how nodes and services are connected—all in real time.",[3522,3523,3524,3525,3524,3530],"figure",{},"\n  ",[2257,3526],{"src":3527,"alt":3240,"title":3528,"className":3529},"blog-images/mission-control-preview-art.png","Visit Computer Hope",[3242,2263],[3531,3532,3534],"figcaption",{"style":3533},"text-align: center;","Stay tuned for its release at the end of this year!",[108,3536,3537],{"id":2182},"What’s Next?",[16,3539,3540,3541,467],{},"Check out our\n",[26,3542,3188],{"href":3186,"rel":3543},[30],[16,3545,3546],{},"In the next release, we plan to focus on:",[20,3548,3549,3555,3573,3579,3585],{},[23,3550,3551,3554],{},[72,3552,3553],{},"Finalizing the C/C++ language bindings",": Most of the Rust functionality\nworks, but features like dynamic slice support and service attributes are\nstill in progress.",[23,3556,3557,3560,3561,3564,3565],{},[72,3558,3559],{},"Event multiplexing",": We’re extending ",[150,3562,3563],{},"Node::wait()"," for more streamlined\nevent handling.\n",[20,3566,3567,3570],{},[23,3568,3569],{},"This will come with advanced integrated events, such as push notifications\nfor system events like process crashes or service changes.",[23,3571,3572],{},"Expect detailed examples and documentation.",[23,3574,3575,3578],{},[72,3576,3577],{},"Services with dynamic payloads",": You won’t need to define a fixed payload\nsize for services with slices anymore. We’ll introduce an allocation\nalgorithm that acquires more shared memory as needed, and it’ll be\ncustomizable.",[23,3580,3581,3584],{},[72,3582,3583],{},"Health monitoring",": With iceoryx2 nodes, we can detect dead nodes and\nclean up their resources. The next step is to actively notify processes\nwhen a sender or receiver dies.",[23,3586,3587,3590],{},[72,3588,3589],{},"Expanded documentation",": Inter-process communication can be complex, so\nwe’re working on extending the docs to provide a gentle introduction,\nexplain iceoryx2's features in detail, and offer a step-by-step tutorial on\nmaking the most of it.",{"title":183,"searchDepth":217,"depth":217,"links":3592},[3593,3594,3597,3598],{"id":2219,"depth":217,"text":2220},{"id":3250,"depth":217,"text":3251,"children":3595},[3596],{"id":3382,"depth":229,"text":3383},{"id":3516,"depth":217,"text":3517},{"id":2182,"depth":217,"text":3537},"2024-09-28T00:00:00.000Z","Announcing the release of iceoryx2 version 0.4.0, highlighting key features like daemon-less operation, improved performance, enhanced modularity, and C/C++ language bindings.",{},"/blog/iceoryx2-0-4-release",{"title":3228,"description":3600},"blog/iceoryx2-0-4-release",[1295,3224,384,3606,3607],"cpp","c","AxNwg_99ELtjQLUTuuuAGsy0DRvd2BJ6ZGr_TtbnQCg",{"id":3610,"title":3611,"author":7,"body":3612,"date":5033,"description":5034,"extension":1287,"featured":1288,"image":1289,"meta":5035,"navigation":239,"path":5036,"seo":5037,"stem":5038,"tags":5039,"__hash__":5040},"blog/blog/iceoryx2-0-5-release.md","Announcing iceoryx2 v0.5.0",{"type":9,"value":3613,"toc":5022},[3614,3617,3620,3623,3625,3630,3637,3641,3644,3673,3677,3686,3690,3696,3699,3706,3709,3874,3882,3888,3891,3894,3903,3930,3933,4118,4135,4137,4440,4447,4452,4511,4516,4519,4528,4542,4545,4916,4937,4950,4955,4963,4966,4968,4974,4977,5019],[12,3615,3611],{"id":3616},"announcing-iceoryx2-v050",[16,3618,3619],{},"Christian Eltzschig - 23/12/2024",[2257,3621],{"src":3239,"alt":3240,"className":3622},[3242,2263],[108,3624,2220],{"id":2219},[16,3626,3627,3629],{},[72,3628,1295],{}," is a service-based inter-process communication (IPC) library\ndesigned to build robust and efficient decentralized systems. It enables\nultra low-latency communication between processes — similar to Unix domain\nsockets or message queues, but significantly faster and easier to use.",[16,3631,3632,3633,3636],{},"Check out the\n",[26,3634,175],{"href":173,"rel":3635},[30],"\nand try them out on your platform!",[2257,3638],{"src":3639,"alt":3377,"className":3640},"blog-images/benchmark.png",[3379,2263],[16,3642,3643],{},"It also comes with advanced features such as circular buffers, history, event\nnotifications, publish-subscribe messaging, and a decentralized architecture\nwith no need for a broker.",[20,3645,3646,3652,3658,3663,3668],{},[23,3647,3648],{},[26,3649,31],{"href":3650,"rel":3651},"https://www.reddit.com/r/programming/comments/1hktm3a/announcing_iceoryx2_v05_fast_and_robust/",[30],[23,3653,3654],{},[26,3655,38],{"href":3656,"rel":3657},"https://news.ycombinator.com/item?id=42496355",[30],[23,3659,3660],{},[26,3661,47],{"href":45,"rel":3662},[30],[23,3664,3665],{},[26,3666,54],{"href":52,"rel":3667},[30],[23,3669,3670],{},[26,3671,61],{"href":59,"rel":3672},[30],[108,3674,3676],{"id":3675},"release-v050","Release v0.5.0",[16,3678,3679,3680,3685],{},"The\n",[26,3681,3684],{"href":3682,"rel":3683},"https://github.com/eclipse-iceoryx/iceoryx2/releases/tag/v0.5.0",[30],"iceoryx2 v0.5.0 release",",\nintroduces several features to improve the user experience, including support for\ndynamic payloads, allowing publishers to handle variable payload sizes without\nthe need to predefine maximum payload sizes. It also introduces health monitoring\ninforming users when a process crashes in a decentralized\nsystem. The new WaitSet enables efficient event management by waiting on\nmultiple events like listeners or sockets in a single call. Furthermore, it\ncomes with advanced features such as deadlines and intervals to manage\ntiming constraints.\nThis makes a decentralized architecture more robust by allowing proactive\nhandling of missed notifications and failed processes.",[108,3687,3689],{"id":3688},"feature-deep-dive","Feature Deep-Dive",[113,3691,3693],{"id":3692},"dynamic-payload-memory",[72,3694,3695],{},"Dynamic Payload Memory",[16,3697,3698],{},"One highly requested feature was the ability for publishers to handle dynamic\npayloads. This means you no longer need to know the payload size in advance,\nand the publisher can reallocate memory as needed. While this might seem\ntrivial, it’s quite challenging in the context of shared-memory-based\ncommunication.",[16,3700,3701,3702,3705],{},"The dynamic payload works in combination with the slice API by simply defining\nan ",[150,3703,3704],{},"AllocationStrategy"," when creating a new publisher, and iceoryx2\nautomatically handles memory reallocation for you.",[16,3707,3708],{},"Here’s an example:",[178,3710,3712],{"className":382,"code":3711,"language":384,"meta":183,"style":183},"let service = node\n    .service_builder(&\"Service With Dynamic Data\".try_into()?)\n    .publish_subscribe::\u003C[u8]>()\n    .open_or_create()?;\n\nlet publisher = service\n    .publisher_builder()\n    // We guess that the samples are at most 16 bytes in size.\n    // This is just a hint to the underlying allocator and is purely optional.\n    // A better guess minimizes reallocations.\n    .initial_max_slice_len(16)\n    // The underlying sample size will increase using a power-of-two strategy\n    // when [`Publisher::loan_slice()`] or [`Publisher::loan_slice_uninit()`]\n    // require more memory than currently available.\n    .allocation_strategy(AllocationStrategy::PowerOfTwo)\n    .create()?;\n",[150,3713,3714,3724,3747,3764,3776,3780,3791,3800,3805,3810,3815,3829,3834,3839,3844,3862],{"__ignoreMap":183},[187,3715,3716,3718,3720,3722],{"class":189,"line":190},[187,3717,438],{"class":391},[187,3719,1355],{"class":410},[187,3721,444],{"class":391},[187,3723,447],{"class":410},[187,3725,3726,3728,3730,3732,3734,3737,3739,3741,3743,3745],{"class":189,"line":217},[187,3727,452],{"class":391},[187,3729,455],{"class":193},[187,3731,458],{"class":410},[187,3733,461],{"class":391},[187,3735,3736],{"class":197},"\"Service With Dynamic Data\"",[187,3738,467],{"class":391},[187,3740,470],{"class":193},[187,3742,473],{"class":410},[187,3744,476],{"class":391},[187,3746,479],{"class":410},[187,3748,3749,3751,3753,3755,3758,3761],{"class":189,"line":229},[187,3750,452],{"class":391},[187,3752,1396],{"class":193},[187,3754,498],{"class":391},[187,3756,3757],{"class":410},"\u003C[",[187,3759,3760],{"class":193},"u8",[187,3762,3763],{"class":410},"]>()\n",[187,3765,3766,3768,3770,3772,3774],{"class":189,"line":236},[187,3767,452],{"class":391},[187,3769,860],{"class":193},[187,3771,473],{"class":410},[187,3773,476],{"class":391},[187,3775,411],{"class":410},[187,3777,3778],{"class":189,"line":243},[187,3779,240],{"emptyLinePlaceholder":239},[187,3781,3782,3784,3786,3788],{"class":189,"line":260},[187,3783,438],{"class":391},[187,3785,1428],{"class":410},[187,3787,444],{"class":391},[187,3789,3790],{"class":410}," service\n",[187,3792,3793,3795,3798],{"class":189,"line":270},[187,3794,452],{"class":391},[187,3796,3797],{"class":193},"publisher_builder",[187,3799,853],{"class":410},[187,3801,3802],{"class":189,"line":276},[187,3803,3804],{"class":232},"    // We guess that the samples are at most 16 bytes in size.\n",[187,3806,3807],{"class":189,"line":281},[187,3808,3809],{"class":232},"    // This is just a hint to the underlying allocator and is purely optional.\n",[187,3811,3812],{"class":189,"line":298},[187,3813,3814],{"class":232},"    // A better guess minimizes reallocations.\n",[187,3816,3817,3819,3822,3824,3827],{"class":189,"line":308},[187,3818,452],{"class":391},[187,3820,3821],{"class":193},"initial_max_slice_len",[187,3823,458],{"class":410},[187,3825,3826],{"class":201},"16",[187,3828,479],{"class":410},[187,3830,3831],{"class":189,"line":314},[187,3832,3833],{"class":232},"    // The underlying sample size will increase using a power-of-two strategy\n",[187,3835,3836],{"class":189,"line":319},[187,3837,3838],{"class":232},"    // when [`Publisher::loan_slice()`] or [`Publisher::loan_slice_uninit()`]\n",[187,3840,3841],{"class":189,"line":336},[187,3842,3843],{"class":232},"    // require more memory than currently available.\n",[187,3845,3846,3848,3851,3853,3855,3857,3860],{"class":189,"line":346},[187,3847,452],{"class":391},[187,3849,3850],{"class":193},"allocation_strategy",[187,3852,458],{"class":410},[187,3854,3704],{"class":193},[187,3856,498],{"class":391},[187,3858,3859],{"class":193},"PowerOfTwo",[187,3861,479],{"class":410},[187,3863,3864,3866,3868,3870,3872],{"class":189,"line":1237},[187,3865,452],{"class":391},[187,3867,595],{"class":193},[187,3869,473],{"class":410},[187,3871,476],{"class":391},[187,3873,411],{"class":410},[16,3875,3876,3877,3489],{},"Checkout\n",[26,3878,3881],{"href":3879,"rel":3880},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/publish_subscribe_dynamic_data",[30],"publish subscribe with dynamic data example",[113,3883,3885],{"id":3884},"health-monitoring",[72,3886,3887],{},"Health Monitoring",[16,3889,3890],{},"What happens when a critical process crashes, or a service disappears? Wouldn't\nit be great to have a mechanism that informs you immediately, instead of\nleaving you waiting indefinitely?",[16,3892,3893],{},"Health monitoring provides such a mechanism, ensuring you're kept informed\nabout key system events like the appearance or disappearance of services, or\nthe crash of critical processes. In iceoryx2, this is managed in a\ndecentralized manner using Notifier ports.",[16,3895,78,3896,3898,3899,3902],{},[72,3897,3031],{}," is now configurable to emit a \"dead notification\" when a\nprocess is identified as being down. Additionally, the new ",[72,3900,3901],{},"WaitSet"," has been\nintroduced as a key component for efficiently managing notifications and events.",[20,3904,3905,3912,3915],{},[23,3906,3907,3908,3911],{},"You can iterate over all nodes, and if a node is in a ",[72,3909,3910],{},"dead state","\n(e.g., its owning process crashed), you can explicitly clean up stale nodes\nand inform other processes.",[23,3913,3914],{},"iceoryx2 also performs automatic dead-node checks during critical operations\nthat might impact your system.",[23,3916,3917,3918,3921,3922,3925,3926,467],{},"You can configure this behavior via\n",[150,3919,3920],{},"global.node.cleanup-dead-nodes-on-creation"," and\n",[150,3923,3924],{},"global.node.cleanup-dead-nodes-on-destruction"," in the\n",[26,3927,3929],{"href":2739,"rel":3928},[30],"iceoryx2 configuration",[16,3931,3932],{},"Here’s an example implementation:",[178,3934,3936],{"className":382,"code":3935,"language":384,"meta":183,"style":183},"Node::\u003Cipc::Service>::list(Config::global_config(), |node_state| {\n    if let NodeState::Dead(state) = node_state {\n        println!(\n            \"Detected dead node: {:?}\",\n            state.details().as_ref().map(|v| v.name())\n        );\n        state.remove_stale_resources().expect(\"\");\n    }\n\n    CallbackProgression::Continue\n})?;\n",[150,3937,3938,3984,4006,4012,4019,4062,4067,4092,4096,4100,4110],{"__ignoreMap":183},[187,3939,3940,3943,3945,3947,3950,3952,3954,3957,3959,3962,3964,3967,3969,3972,3975,3977,3980,3982],{"class":189,"line":190},[187,3941,3942],{"class":193},"Node",[187,3944,498],{"class":391},[187,3946,501],{"class":410},[187,3948,3949],{"class":193},"ipc",[187,3951,498],{"class":391},[187,3953,1365],{"class":193},[187,3955,3956],{"class":410},">",[187,3958,498],{"class":391},[187,3960,3961],{"class":193},"list",[187,3963,458],{"class":410},[187,3965,3966],{"class":193},"Config",[187,3968,498],{"class":391},[187,3970,3971],{"class":193},"global_config",[187,3973,3974],{"class":410},"(), ",[187,3976,3120],{"class":391},[187,3978,3979],{"class":410},"node_state",[187,3981,3120],{"class":391},[187,3983,1218],{"class":410},[187,3985,3986,3988,3990,3993,3995,3998,4001,4003],{"class":189,"line":217},[187,3987,1207],{"class":391},[187,3989,1168],{"class":391},[187,3991,3992],{"class":193}," NodeState",[187,3994,498],{"class":391},[187,3996,3997],{"class":193},"Dead",[187,3999,4000],{"class":410},"(state) ",[187,4002,444],{"class":391},[187,4004,4005],{"class":410}," node_state {\n",[187,4007,4008,4010],{"class":189,"line":229},[187,4009,1223],{"class":193},[187,4011,1760],{"class":410},[187,4013,4014,4017],{"class":189,"line":236},[187,4015,4016],{"class":197},"            \"Detected dead node: {:?}\"",[187,4018,2827],{"class":410},[187,4020,4021,4024,4026,4029,4031,4033,4036,4038,4040,4043,4045,4047,4050,4052,4055,4057,4060],{"class":189,"line":243},[187,4022,4023],{"class":410},"            state",[187,4025,467],{"class":391},[187,4027,4028],{"class":193},"details",[187,4030,473],{"class":410},[187,4032,467],{"class":391},[187,4034,4035],{"class":193},"as_ref",[187,4037,473],{"class":410},[187,4039,467],{"class":391},[187,4041,4042],{"class":193},"map",[187,4044,458],{"class":410},[187,4046,3120],{"class":391},[187,4048,4049],{"class":410},"v",[187,4051,3120],{"class":391},[187,4053,4054],{"class":410}," v",[187,4056,467],{"class":391},[187,4058,4059],{"class":193},"name",[187,4061,844],{"class":410},[187,4063,4064],{"class":189,"line":260},[187,4065,4066],{"class":410},"        );\n",[187,4068,4069,4072,4074,4077,4079,4081,4084,4086,4089],{"class":189,"line":270},[187,4070,4071],{"class":410},"        state",[187,4073,467],{"class":391},[187,4075,4076],{"class":193},"remove_stale_resources",[187,4078,473],{"class":410},[187,4080,467],{"class":391},[187,4082,4083],{"class":193},"expect",[187,4085,458],{"class":410},[187,4087,4088],{"class":197},"\"\"",[187,4090,4091],{"class":410},");\n",[187,4093,4094],{"class":189,"line":276},[187,4095,1240],{"class":410},[187,4097,4098],{"class":189,"line":281},[187,4099,240],{"emptyLinePlaceholder":239},[187,4101,4102,4105,4107],{"class":189,"line":298},[187,4103,4104],{"class":193},"    CallbackProgression",[187,4106,498],{"class":391},[187,4108,4109],{"class":193},"Continue\n",[187,4111,4112,4114,4116],{"class":189,"line":308},[187,4113,3143],{"class":410},[187,4115,476],{"class":391},[187,4117,411],{"class":410},[16,4119,4120,4121,4123,4124,4129,4130,4132,4133,467],{},"You can also configure a ",[150,4122,3031],{}," to emit a signal as soon as it is\nidentified as dead. This occurs when another process calls\n",[187,4125,4126],{},[150,4127,4128],{},"DeadNode::remove_stale_resources()",". In such cases, the corresponding\n",[150,4131,3038],{}," will be woken up with a predefined ",[150,4134,985],{},[16,4136,3932],{},[178,4138,4140],{"className":382,"code":4139,"language":384,"meta":183,"style":183},"let service_event = node\n    .service_builder(&\"MyEventName\".try_into()?)\n    .event()\n    .notifier_created_event(EventId::new(1))\n    .notifier_dropped_event(EventId::new(2))\n    .notifier_dead_event(EventId::new(3))\n    .open_or_create()?;\n\nlet listener = service_event.listener_builder().create()?;\n\nif let Ok(Some(event_id)) = listener.blocking_wait_one(CYCLE_TIME) {\n    match event_id {\n        EventId::new(1) => println!(\"A new notifier was created.\"),\n        EventId::new(2) => println!(\"A notifier was dropped.\"),\n        EventId::new(3) => println!(\"A notifier was identified as dead.\"),\n        _ => println!(\"An unknown event occurred: {:?}\", event_id),\n    }\n}\n",[150,4141,4142,4153,4176,4184,4206,4228,4250,4262,4266,4293,4297,4327,4335,4364,4389,4414,4431,4435],{"__ignoreMap":183},[187,4143,4144,4146,4149,4151],{"class":189,"line":190},[187,4145,438],{"class":391},[187,4147,4148],{"class":410}," service_event ",[187,4150,444],{"class":391},[187,4152,447],{"class":410},[187,4154,4155,4157,4159,4161,4163,4166,4168,4170,4172,4174],{"class":189,"line":217},[187,4156,452],{"class":391},[187,4158,455],{"class":193},[187,4160,458],{"class":410},[187,4162,461],{"class":391},[187,4164,4165],{"class":197},"\"MyEventName\"",[187,4167,467],{"class":391},[187,4169,470],{"class":193},[187,4171,473],{"class":410},[187,4173,476],{"class":391},[187,4175,479],{"class":410},[187,4177,4178,4180,4182],{"class":189,"line":229},[187,4179,452],{"class":391},[187,4181,795],{"class":193},[187,4183,853],{"class":410},[187,4185,4186,4188,4191,4193,4195,4197,4199,4201,4204],{"class":189,"line":236},[187,4187,452],{"class":391},[187,4189,4190],{"class":193},"notifier_created_event",[187,4192,458],{"class":410},[187,4194,985],{"class":193},[187,4196,498],{"class":391},[187,4198,542],{"class":193},[187,4200,458],{"class":410},[187,4202,4203],{"class":201},"1",[187,4205,550],{"class":410},[187,4207,4208,4210,4213,4215,4217,4219,4221,4223,4226],{"class":189,"line":243},[187,4209,452],{"class":391},[187,4211,4212],{"class":193},"notifier_dropped_event",[187,4214,458],{"class":410},[187,4216,985],{"class":193},[187,4218,498],{"class":391},[187,4220,542],{"class":193},[187,4222,458],{"class":410},[187,4224,4225],{"class":201},"2",[187,4227,550],{"class":410},[187,4229,4230,4232,4235,4237,4239,4241,4243,4245,4248],{"class":189,"line":260},[187,4231,452],{"class":391},[187,4233,4234],{"class":193},"notifier_dead_event",[187,4236,458],{"class":410},[187,4238,985],{"class":193},[187,4240,498],{"class":391},[187,4242,542],{"class":193},[187,4244,458],{"class":410},[187,4246,4247],{"class":201},"3",[187,4249,550],{"class":410},[187,4251,4252,4254,4256,4258,4260],{"class":189,"line":270},[187,4253,452],{"class":391},[187,4255,860],{"class":193},[187,4257,473],{"class":410},[187,4259,476],{"class":391},[187,4261,411],{"class":410},[187,4263,4264],{"class":189,"line":276},[187,4265,240],{"emptyLinePlaceholder":239},[187,4267,4268,4270,4272,4274,4277,4279,4281,4283,4285,4287,4289,4291],{"class":189,"line":281},[187,4269,438],{"class":391},[187,4271,1130],{"class":410},[187,4273,444],{"class":391},[187,4275,4276],{"class":410}," service_event",[187,4278,467],{"class":391},[187,4280,1139],{"class":193},[187,4282,473],{"class":410},[187,4284,467],{"class":391},[187,4286,595],{"class":193},[187,4288,473],{"class":410},[187,4290,476],{"class":391},[187,4292,411],{"class":410},[187,4294,4295],{"class":189,"line":298},[187,4296,240],{"emptyLinePlaceholder":239},[187,4298,4299,4301,4303,4305,4307,4309,4312,4314,4316,4318,4320,4322,4325],{"class":189,"line":308},[187,4300,1165],{"class":391},[187,4302,1168],{"class":391},[187,4304,1171],{"class":193},[187,4306,458],{"class":410},[187,4308,1176],{"class":193},[187,4310,4311],{"class":410},"(event_id)) ",[187,4313,444],{"class":391},[187,4315,1184],{"class":410},[187,4317,467],{"class":391},[187,4319,3072],{"class":193},[187,4321,458],{"class":410},[187,4323,4324],{"class":201},"CYCLE_TIME",[187,4326,1197],{"class":410},[187,4328,4329,4332],{"class":189,"line":314},[187,4330,4331],{"class":391},"    match",[187,4333,4334],{"class":410}," event_id {\n",[187,4336,4337,4340,4342,4344,4346,4348,4351,4354,4357,4359,4362],{"class":189,"line":319},[187,4338,4339],{"class":193},"        EventId",[187,4341,498],{"class":391},[187,4343,542],{"class":193},[187,4345,458],{"class":410},[187,4347,4203],{"class":201},[187,4349,4350],{"class":410},") ",[187,4352,4353],{"class":391},"=>",[187,4355,4356],{"class":193}," println!",[187,4358,458],{"class":410},[187,4360,4361],{"class":197},"\"A new notifier was created.\"",[187,4363,1813],{"class":410},[187,4365,4366,4368,4370,4372,4374,4376,4378,4380,4382,4384,4387],{"class":189,"line":336},[187,4367,4339],{"class":193},[187,4369,498],{"class":391},[187,4371,542],{"class":193},[187,4373,458],{"class":410},[187,4375,4225],{"class":201},[187,4377,4350],{"class":410},[187,4379,4353],{"class":391},[187,4381,4356],{"class":193},[187,4383,458],{"class":410},[187,4385,4386],{"class":197},"\"A notifier was dropped.\"",[187,4388,1813],{"class":410},[187,4390,4391,4393,4395,4397,4399,4401,4403,4405,4407,4409,4412],{"class":189,"line":346},[187,4392,4339],{"class":193},[187,4394,498],{"class":391},[187,4396,542],{"class":193},[187,4398,458],{"class":410},[187,4400,4247],{"class":201},[187,4402,4350],{"class":410},[187,4404,4353],{"class":391},[187,4406,4356],{"class":193},[187,4408,458],{"class":410},[187,4410,4411],{"class":197},"\"A notifier was identified as dead.\"",[187,4413,1813],{"class":410},[187,4415,4416,4419,4421,4423,4425,4428],{"class":189,"line":1237},[187,4417,4418],{"class":410},"        _ ",[187,4420,4353],{"class":391},[187,4422,4356],{"class":193},[187,4424,458],{"class":410},[187,4426,4427],{"class":197},"\"An unknown event occurred: {:?}\"",[187,4429,4430],{"class":410},", event_id),\n",[187,4432,4433],{"class":189,"line":1243},[187,4434,1240],{"class":410},[187,4436,4438],{"class":189,"line":4437},18,[187,4439,1246],{"class":410},[16,4441,3876,4442,3489],{},[26,4443,4446],{"href":4444,"rel":4445},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/health_monitoring",[30],"health monitoring example",[4448,4449,4451],"h4",{"id":4450},"details-of-the-key-concepts","Details of the Key Concepts",[2286,4453,4454,4490,4503],{},[23,4455,4456,398,4459],{},[72,4457,4458],{},"Notifier Events",[20,4460,4461,4471,4481],{},[23,4462,4463,4467,4468,4470],{},[72,4464,4465],{},[150,4466,4190],{},": Triggered when a new ",[150,4469,3031],{}," port is\ncreated.",[23,4472,4473,4477,4478,4480],{},[72,4474,4475],{},[150,4476,4212],{},": Triggered when a ",[150,4479,3031],{}," port is dropped.",[23,4482,4483,4477,4487,4489],{},[72,4484,4485],{},[150,4486,4234],{},[150,4488,3031],{}," owned by a dead node\nis detected, and all its stale resources are successfully removed.",[23,4491,4492,4494,4495,4497,4498,4500,4501,467],{},[72,4493,3038],{},":\nThe ",[150,4496,3038],{}," listens for events emitted by the ",[150,4499,3031],{},". When an event\noccurs, the listener wakes up and identifies the event based on the\nassociated ",[150,4502,985],{},[23,4504,4505,4494,4508,4510],{},[72,4506,4507],{},"Dead Node Handling",[150,4509,4234],{}," ensures the system can respond effectively to\ncrashes by notifying the corresponding listeners.",[113,4512,4514],{"id":4513},"waitset",[72,4515,3901],{},[16,4517,4518],{},"The WaitSet is iceoryx2’s new event multiplexer, allowing you to wait on\nmultiple events — such as iceoryx2 listeners or sockets — in a single call.\nWhether you’re waiting for incoming messages from a third-party network stack or\niceoryx2 notifications, the WaitSet has you covered.",[16,4520,4521,4522,2570,4525,398],{},"It also includes advanced features like ",[72,4523,4524],{},"deadlines",[72,4526,4527],{},"intervals",[20,4529,4530,4536],{},[23,4531,4532,4535],{},[72,4533,4534],{},"Deadlines",": Set timing constraints for incoming messages. If a message\nisn’t received within the defined timeframe, the WaitSet wakes you up and\ninforms you which deadline was hit.",[23,4537,4538,4541],{},[72,4539,4540],{},"Intervals",": Configure the WaitSet to wake you up at regular intervals.",[16,4543,4544],{},"And another example:",[178,4546,4548],{"className":382,"code":4547,"language":384,"meta":183,"style":183},"let waitset = WaitSetBuilder::new().create::\u003Cipc::Service>()?;\n\n// Attach intervals\nlet interval_1_guard = waitset.attach_interval(Duration::from_secs(2))?;\nlet interval_2_guard = waitset.attach_interval(Duration::from_secs(3))?;\n\n// Attach a deadline and a notification\nlet deadline_guard = waitset.attach_deadline(my_listener, Duration::from_secs(1))?;\nlet notification_guard = waitset.attach_notification(another_listener)?;\n\n// Define the callback to handle events\nlet on_event = |attachment_id: WaitSetAttachmentId\u003Cipc::Service>| {\n    if attachment_id.has_event_from(interval_1_guard) {\n        // Action for events every 2 seconds\n    } else if attachment_id.has_event_from(interval_2_guard) {\n        // Action for events every 3 seconds\n    } else if attachment_id.has_event_from(deadline_guard) {\n        // Received data within the 1-second deadline\n    } else if attachment_id.has_missed_deadline(deadline_guard) {\n        // No data received within the 1-second deadline\n    }\n    CallbackProgression::Continue\n};\n\n// Wait and process events\nwaitset.wait_and_process(on_event)?;\n",[150,4549,4550,4589,4593,4598,4636,4669,4673,4678,4713,4736,4740,4745,4778,4793,4798,4818,4823,4840,4845,4863,4869,4874,4883,4888,4893,4899],{"__ignoreMap":183},[187,4551,4552,4554,4557,4559,4562,4564,4566,4568,4570,4572,4574,4576,4578,4580,4582,4585,4587],{"class":189,"line":190},[187,4553,438],{"class":391},[187,4555,4556],{"class":410}," waitset ",[187,4558,444],{"class":391},[187,4560,4561],{"class":193}," WaitSetBuilder",[187,4563,498],{"class":391},[187,4565,542],{"class":193},[187,4567,473],{"class":410},[187,4569,467],{"class":391},[187,4571,595],{"class":193},[187,4573,498],{"class":391},[187,4575,501],{"class":410},[187,4577,3949],{"class":193},[187,4579,498],{"class":391},[187,4581,1365],{"class":193},[187,4583,4584],{"class":410},">()",[187,4586,476],{"class":391},[187,4588,411],{"class":410},[187,4590,4591],{"class":189,"line":217},[187,4592,240],{"emptyLinePlaceholder":239},[187,4594,4595],{"class":189,"line":229},[187,4596,4597],{"class":232},"// Attach intervals\n",[187,4599,4600,4602,4605,4607,4610,4612,4615,4617,4620,4622,4625,4627,4629,4632,4634],{"class":189,"line":236},[187,4601,438],{"class":391},[187,4603,4604],{"class":410}," interval_1_guard ",[187,4606,444],{"class":391},[187,4608,4609],{"class":410}," waitset",[187,4611,467],{"class":391},[187,4613,4614],{"class":193},"attach_interval",[187,4616,458],{"class":410},[187,4618,4619],{"class":193},"Duration",[187,4621,498],{"class":391},[187,4623,4624],{"class":193},"from_secs",[187,4626,458],{"class":410},[187,4628,4225],{"class":201},[187,4630,4631],{"class":410},"))",[187,4633,476],{"class":391},[187,4635,411],{"class":410},[187,4637,4638,4640,4643,4645,4647,4649,4651,4653,4655,4657,4659,4661,4663,4665,4667],{"class":189,"line":243},[187,4639,438],{"class":391},[187,4641,4642],{"class":410}," interval_2_guard ",[187,4644,444],{"class":391},[187,4646,4609],{"class":410},[187,4648,467],{"class":391},[187,4650,4614],{"class":193},[187,4652,458],{"class":410},[187,4654,4619],{"class":193},[187,4656,498],{"class":391},[187,4658,4624],{"class":193},[187,4660,458],{"class":410},[187,4662,4247],{"class":201},[187,4664,4631],{"class":410},[187,4666,476],{"class":391},[187,4668,411],{"class":410},[187,4670,4671],{"class":189,"line":260},[187,4672,240],{"emptyLinePlaceholder":239},[187,4674,4675],{"class":189,"line":270},[187,4676,4677],{"class":232},"// Attach a deadline and a notification\n",[187,4679,4680,4682,4685,4687,4689,4691,4694,4697,4699,4701,4703,4705,4707,4709,4711],{"class":189,"line":276},[187,4681,438],{"class":391},[187,4683,4684],{"class":410}," deadline_guard ",[187,4686,444],{"class":391},[187,4688,4609],{"class":410},[187,4690,467],{"class":391},[187,4692,4693],{"class":193},"attach_deadline",[187,4695,4696],{"class":410},"(my_listener, ",[187,4698,4619],{"class":193},[187,4700,498],{"class":391},[187,4702,4624],{"class":193},[187,4704,458],{"class":410},[187,4706,4203],{"class":201},[187,4708,4631],{"class":410},[187,4710,476],{"class":391},[187,4712,411],{"class":410},[187,4714,4715,4717,4720,4722,4724,4726,4729,4732,4734],{"class":189,"line":281},[187,4716,438],{"class":391},[187,4718,4719],{"class":410}," notification_guard ",[187,4721,444],{"class":391},[187,4723,4609],{"class":410},[187,4725,467],{"class":391},[187,4727,4728],{"class":193},"attach_notification",[187,4730,4731],{"class":410},"(another_listener)",[187,4733,476],{"class":391},[187,4735,411],{"class":410},[187,4737,4738],{"class":189,"line":298},[187,4739,240],{"emptyLinePlaceholder":239},[187,4741,4742],{"class":189,"line":308},[187,4743,4744],{"class":232},"// Define the callback to handle events\n",[187,4746,4747,4749,4752,4754,4757,4760,4762,4765,4768,4770,4772,4774,4776],{"class":189,"line":314},[187,4748,438],{"class":391},[187,4750,4751],{"class":410}," on_event ",[187,4753,444],{"class":391},[187,4755,4756],{"class":391}," |",[187,4758,4759],{"class":410},"attachment_id",[187,4761,398],{"class":391},[187,4763,4764],{"class":193}," WaitSetAttachmentId",[187,4766,4767],{"class":410},"\u003Cipc",[187,4769,498],{"class":391},[187,4771,1365],{"class":193},[187,4773,3956],{"class":410},[187,4775,3120],{"class":391},[187,4777,1218],{"class":410},[187,4779,4780,4782,4785,4787,4790],{"class":189,"line":319},[187,4781,1207],{"class":391},[187,4783,4784],{"class":410}," attachment_id",[187,4786,467],{"class":391},[187,4788,4789],{"class":193},"has_event_from",[187,4791,4792],{"class":410},"(interval_1_guard) {\n",[187,4794,4795],{"class":189,"line":336},[187,4796,4797],{"class":232},"        // Action for events every 2 seconds\n",[187,4799,4800,4803,4806,4809,4811,4813,4815],{"class":189,"line":346},[187,4801,4802],{"class":410},"    } ",[187,4804,4805],{"class":391},"else",[187,4807,4808],{"class":391}," if",[187,4810,4784],{"class":410},[187,4812,467],{"class":391},[187,4814,4789],{"class":193},[187,4816,4817],{"class":410},"(interval_2_guard) {\n",[187,4819,4820],{"class":189,"line":1237},[187,4821,4822],{"class":232},"        // Action for events every 3 seconds\n",[187,4824,4825,4827,4829,4831,4833,4835,4837],{"class":189,"line":1243},[187,4826,4802],{"class":410},[187,4828,4805],{"class":391},[187,4830,4808],{"class":391},[187,4832,4784],{"class":410},[187,4834,467],{"class":391},[187,4836,4789],{"class":193},[187,4838,4839],{"class":410},"(deadline_guard) {\n",[187,4841,4842],{"class":189,"line":4437},[187,4843,4844],{"class":232},"        // Received data within the 1-second deadline\n",[187,4846,4848,4850,4852,4854,4856,4858,4861],{"class":189,"line":4847},19,[187,4849,4802],{"class":410},[187,4851,4805],{"class":391},[187,4853,4808],{"class":391},[187,4855,4784],{"class":410},[187,4857,467],{"class":391},[187,4859,4860],{"class":193},"has_missed_deadline",[187,4862,4839],{"class":410},[187,4864,4866],{"class":189,"line":4865},20,[187,4867,4868],{"class":232},"        // No data received within the 1-second deadline\n",[187,4870,4872],{"class":189,"line":4871},21,[187,4873,1240],{"class":410},[187,4875,4877,4879,4881],{"class":189,"line":4876},22,[187,4878,4104],{"class":193},[187,4880,498],{"class":391},[187,4882,4109],{"class":193},[187,4884,4886],{"class":189,"line":4885},23,[187,4887,2832],{"class":410},[187,4889,4891],{"class":189,"line":4890},24,[187,4892,240],{"emptyLinePlaceholder":239},[187,4894,4896],{"class":189,"line":4895},25,[187,4897,4898],{"class":232},"// Wait and process events\n",[187,4900,4902,4904,4906,4909,4912,4914],{"class":189,"line":4901},26,[187,4903,4513],{"class":410},[187,4905,467],{"class":391},[187,4907,4908],{"class":193},"wait_and_process",[187,4910,4911],{"class":410},"(on_event)",[187,4913,476],{"class":391},[187,4915,411],{"class":410},[16,4917,4918,4919,4922,4923,4926,4927,4930,4931,4926,4934,467],{},"You can also attach anything that implements ",[150,4920,4921],{},"SynchronousMultiplexing",". For\nexample, if you have a socket or file descriptor that works with C calls like\n",[150,4924,4925],{},"epoll"," or ",[150,4928,4929],{},"select",", you simply need to implement the trait, and it can then be\nused with ",[150,4932,4933],{},"WaitSet::attach_deadline()",[150,4935,4936],{},"WaitSet::attach_notification()",[16,4938,3876,4939,4944,4945,3489],{},[26,4940,4943],{"href":4941,"rel":4942},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/event_multiplexing",[30],"event multiplexing example","\nand\n",[26,4946,4949],{"href":4947,"rel":4948},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/event_based_communication",[30],"event based communication example",[113,4951,4953],{"id":4952},"rmw_iceoryx2",[72,4954,4952],{},[16,4956,4957,4958,4962],{},"We have released the first version of the\n",[26,4959,4961],{"href":52,"rel":4960},[30],"iceoryx2 RMW ROS 2 binding",",\nallowing\niceoryx2 to be used as a transport layer for ROS 2. This provides a significant\nreduction in latency while lowering the CPU and memory load on your system.",[16,4964,4965],{},"Another advantage is that it offers a pathway to transition from a ROS 2 system\nto a safety-certified system. The iceoryx2 layer will soon be certifiable and\ncapable of communicating with all ROS 2 nodes. This allows you to port\napplications to the iceoryx2 API one by one, as needed for certification, while\nmaintaining communication with the rest of the system. This approach allows\na smooth and incremental transition from proof-of-concept to production-ready\nsystems.",[108,4967,3537],{"id":2182},[16,4969,3540,4970,4973],{},[26,4971,3188],{"href":3186,"rel":4972},[30]," to\nstay updated on our plans and progress.",[16,4975,4976],{},"For the next release, we plan to focus on:",[20,4978,4979,4982,4985,4991,5005],{},[23,4980,4981],{},"Request/Response",[23,4983,4984],{},"Python Language Binding",[23,4986,4987,4988,4990],{},"Gateways: We start with ",[72,4989,3355],{},", and then other protocols like MQTT or DDS\nwill follow.",[23,4992,4993,4994,4997,4998,3425,5001,5004],{},"OS Support: ",[72,4995,4996],{},"QNX"," (maybe ",[72,4999,5000],{},"Android",[72,5002,5003],{},"iOS"," support in sandbox mode)",[23,5006,5007,5008],{},"Expanded Documentation: Recognizing the complexities of inter-process\ncommunication, we are enhancing our documentation to:\n",[20,5009,5010,5013,5016],{},[23,5011,5012],{},"Provide a gentle introduction for new users,",[23,5014,5015],{},"Explain iceoryx2’s features in detail,",[23,5017,5018],{},"Offer step-by-step tutorials to help you make the most of the library.",[1271,5020,5021],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":183,"searchDepth":217,"depth":217,"links":5023},[5024,5025,5026,5032],{"id":2219,"depth":217,"text":2220},{"id":3675,"depth":217,"text":3676},{"id":3688,"depth":217,"text":3689,"children":5027},[5028,5029,5030,5031],{"id":3692,"depth":229,"text":3695},{"id":3884,"depth":229,"text":3887},{"id":4513,"depth":229,"text":3901},{"id":4952,"depth":229,"text":4952},{"id":2182,"depth":217,"text":3537},"2024-12-23T00:00:00.000Z","Announcing the release of iceoryx2 version 0.5.0, introducing dynamic payloads, health monitoring, the new WaitSet for event management, and the rmw_iceoryx2 ROS 2 binding.",{},"/blog/iceoryx2-0-5-release",{"title":3611,"description":5034},"blog/iceoryx2-0-5-release",[1295,3224,384,3606,3607],"F87frKr3KOIicU0Vf0ILebRjbhf9F61HI9qzcV-QyZA",{"id":5042,"title":5043,"author":7,"body":5044,"date":6166,"description":6167,"extension":1287,"featured":1288,"image":1289,"meta":6168,"navigation":239,"path":6169,"seo":6170,"stem":6171,"tags":6172,"__hash__":6173},"blog/blog/iceoryx2-0-6-release.md","Announcing iceoryx2 v0.6.0",{"type":9,"value":5045,"toc":6160},[5046,5049,5052,5055,5057,5061,5064,5067,5072,5075,5104,5108,5116,5154,5157,5162,5165,5169,5172,5175,5178,5182,5185,5187,5190,5206,5215,5218,5221,5224,5231,5369,5372,5379,5382,5542,5550,5554,5557,5560,5563,5654,5657,5660,5667,5670,5685,5691,5702,5709,5712,5715,5730,5733,5798,5801,5818,5821,5834,5837,5867,5870,5886,5890,5893,5896,5912,5920,5934,5937,5940,5943,5946,5965,5968,5978,5997,6005,6021,6027,6030,6036,6044,6050,6068,6078,6096,6100,6108,6137,6142,6146,6149,6152,6157],[12,5047,5043],{"id":5048},"announcing-iceoryx2-v060",[16,5050,5051],{},"Christian Eltzschig - 17/05/2025",[2257,5053],{"src":3239,"alt":3240,"className":5054},[3242,2263],[113,5056,2220],{"id":2219},[16,5058,5059,3629],{},[72,5060,1295],{},[16,5062,5063],{},"It includes language bindings for C, C++, and Rust, with support for Python\nplanned for an upcoming release.",[16,5065,5066],{},"iceoryx2 supports messaging patterns such as publish-subscribe, events, and the\nnewly introduced request-response stream pattern. It is robust and comes with\na decentralized architecture without the need for a central broker.",[16,5068,3632,5069,3636],{},[26,5070,175],{"href":173,"rel":5071},[30],[2257,5073],{"src":3639,"alt":3377,"className":5074},[3379,2263],[20,5076,5077,5083,5089,5094,5099],{},[23,5078,5079],{},[26,5080,31],{"href":5081,"rel":5082},"https://www.reddit.com/r/programming/comments/1kp0i2g/iceoryx2_v060_is_out_highperformance/",[30],[23,5084,5085],{},[26,5086,2622],{"href":5087,"rel":5088},"https://programming.dev/post/30565644",[30],[23,5090,5091],{},[26,5092,47],{"href":45,"rel":5093},[30],[23,5095,5096],{},[26,5097,54],{"href":52,"rel":5098},[30],[23,5100,5101],{},[26,5102,61],{"href":59,"rel":5103},[30],[113,5105,5107],{"id":5106},"release-v060","Release v0.6.0",[16,5109,5110,5111,467],{},"Our small company is steadily growing, thanks to our community and our\nsupportive customers. This growth has enabled us to deliver one of our biggest\nreleases yet in terms of features: the\n",[26,5112,5115],{"href":5113,"rel":5114},"https://github.com/eclipse-iceoryx/iceoryx2/releases/tag/v0.6.0",[30],"iceoryx2 v0.6.0 release",[20,5117,5118,5124,5130,5136,5142,5148],{},[23,5119,5120],{},[26,5121,5123],{"href":5122},"#request-response-stream","Request-Response Stream",[23,5125,5126],{},[26,5127,5129],{"href":5128},"#zero-copy-cross-language-inter-process-communication","Zero-Copy Cross-Language Inter-Process Communication",[23,5131,5132],{},[26,5133,5135],{"href":5134},"#command-line-client","Command Line Client",[23,5137,5138],{},[26,5139,5141],{"href":5140},"#microservice-architecture-and-built-in-services","Microservice Architecture and BuiltIn Services",[23,5143,5144],{},[26,5145,5147],{"href":5146},"#zerocopysend","ZeroCopySend and Type-Safe Communication",[23,5149,5150],{},[26,5151,5153],{"href":5152},"#other-feature-highlights","Other Feature Highlights",[4448,5155,5123],{"id":5156},"request-response-stream",[5158,5159,5161],"h5",{"id":5160},"introduction","Introduction",[16,5163,5164],{},"The well-known request-response messaging pattern involves a client sending a\nrequest to a server and receiving a corresponding response. A typical example\nis an operator commanding a robot to move to a specific position, with the\nrobot confirming the command by sending back a response. This is now supported\nin iceoryx2 - along with much more.",[5158,5166,5168],{"id":5167},"operating-a-robot","Operating A Robot",[16,5170,5171],{},"In addition to a one-time response, the operator might also be interested in\nmonitoring the robot’s progress in real time. With iceoryx2, a request can\ninitiate a stream of responses - hence the name request-response stream.\nInstead of simply acknowledging the request, the server can continuously send\nposition updates as the robot moves. Once the robot reaches its destination,\nthe server drops the corresponding object, signaling completion to the client.",[16,5173,5174],{},"Conversely, if the client loses interest - for example, due to a canceled\noperation - it can let its corresponding object go out of scope. This informs\nthe server to stop processing the request, which could include halting the\nrobot.",[16,5176,5177],{},"Thanks to iceoryx2’s new API, this is implemented with maximum efficiency.\nUsers don’t need to manage request or response IDs manually. Each\nrequest-response pair operates on a dedicated connection, complete with\nbuilt-in overflow and buffer-size controls.",[5158,5179,5181],{"id":5180},"publish-subscribe-with-a-filter","Publish-Subscribe With A Filter",[16,5183,5184],{},"Suppose you're building a service that analyzes camera images to detect facial\nexpressions. You only want images containing faces - not trees.\nWith request-response stream, you can request just the relevant images and\nreceive them as a filtered stream. Irrelevant images are automatically excluded\non the server side.",[5158,5186,111],{"id":110},[16,5188,5189],{},"Currently, there are two request-response examples available in iceoryx2:",[20,5191,5192,5199],{},[23,5193,5194],{},[26,5195,5198],{"href":5196,"rel":5197},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/request_response",[30],"Getting started with request response",[23,5200,5201],{},[26,5202,5205],{"href":5203,"rel":5204},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/request_response_dynamic_data",[30],"Request response with dynamic data types",[16,5207,5208,5209,5214],{},"Most examples are provided in all supported languages. Check out the\n",[26,5210,5213],{"href":5211,"rel":5212},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples#overview",[30],"examples overview","\nfor details.",[4448,5216,5129],{"id":5217},"zero-copy-cross-language-inter-process-communication",[16,5219,5220],{},"iceoryx2 already supports multiple languages, but until now, it was not\npossible to connect processes written in different languages - for example,\na C++ process with a Rust process. Each process had to remain within its own\nlanguage domain.",[16,5222,5223],{},"This limitation has been resolved by introducing the ability to define a\nsemantic type name in every supported language.",[16,5225,5226,5227,5230],{},"Let’s say you have a type like ",[150,5228,5229],{},"TransmissionData"," that you want to use for\ncommunication between Rust and C++. By assigning a shared semantic type name,\nboth languages can now recognize and interpret the data structure as the same\nconceptual type, enabling seamless zero-copy communication across language\nboundaries.",[5232,5233,5235,5325],"code-tabs",{"tabs":5234},"rust:Rust Implementation,cpp:C++ Implementation",[5236,5237,5238],"template",{"v-slot:rust":183},[178,5239,5241],{"className":382,"code":5240,"language":384,"meta":183,"style":183},"#[derive(Debug, Clone, Copy)]\n#[repr(C)]\npub struct TransmissionData {\n    pub x: i32,\n    pub y: i32,\n    pub funky: u64,\n}\n",[150,5242,5243,5261,5269,5280,5295,5308,5321],{"__ignoreMap":183},[187,5244,5245,5247,5249,5251,5254,5256,5259],{"class":189,"line":190},[187,5246,2841],{"class":410},[187,5248,2844],{"class":193},[187,5250,535],{"class":410},[187,5252,5253],{"class":193},"Clone",[187,5255,535],{"class":410},[187,5257,5258],{"class":193},"Copy",[187,5260,2852],{"class":410},[187,5262,5263,5265,5267],{"class":189,"line":217},[187,5264,2857],{"class":410},[187,5266,2860],{"class":193},[187,5268,2852],{"class":410},[187,5270,5271,5273,5275,5278],{"class":189,"line":229},[187,5272,2867],{"class":391},[187,5274,2870],{"class":391},[187,5276,5277],{"class":193}," TransmissionData",[187,5279,1218],{"class":410},[187,5281,5282,5285,5288,5290,5293],{"class":189,"line":236},[187,5283,5284],{"class":391},"    pub",[187,5286,5287],{"class":410}," x",[187,5289,398],{"class":391},[187,5291,5292],{"class":193}," i32",[187,5294,2827],{"class":410},[187,5296,5297,5299,5302,5304,5306],{"class":189,"line":243},[187,5298,5284],{"class":391},[187,5300,5301],{"class":410}," y",[187,5303,398],{"class":391},[187,5305,5292],{"class":193},[187,5307,2827],{"class":410},[187,5309,5310,5312,5315,5317,5319],{"class":189,"line":260},[187,5311,5284],{"class":391},[187,5313,5314],{"class":410}," funky",[187,5316,398],{"class":391},[187,5318,401],{"class":193},[187,5320,2827],{"class":410},[187,5322,5323],{"class":189,"line":270},[187,5324,1246],{"class":410},[5236,5326,5327],{"v-slot:cpp":183},[178,5328,5331],{"className":5329,"code":5330,"language":3606,"meta":183,"style":183},"language-cpp shiki shiki-themes github-light github-dark","struct TransmissionData {\n    int32_t x;\n    int32_t y;\n    uint64_t funky;\n}\n",[150,5332,5333,5342,5350,5357,5365],{"__ignoreMap":183},[187,5334,5335,5338,5340],{"class":189,"line":190},[187,5336,5337],{"class":391},"struct",[187,5339,5277],{"class":193},[187,5341,1218],{"class":410},[187,5343,5344,5347],{"class":189,"line":217},[187,5345,5346],{"class":391},"    int32_t",[187,5348,5349],{"class":410}," x;\n",[187,5351,5352,5354],{"class":189,"line":229},[187,5353,5346],{"class":391},[187,5355,5356],{"class":410}," y;\n",[187,5358,5359,5362],{"class":189,"line":236},[187,5360,5361],{"class":391},"    uint64_t",[187,5363,5364],{"class":410}," funky;\n",[187,5366,5367],{"class":189,"line":243},[187,5368,1246],{"class":410},[16,5370,5371],{},"With the newly introduced ZeroCopySend derive macro in Rust, you can annotate a\ntype and assign it a unique semantic type name - the identifier under which the\npayload type is known system-wide.",[16,5373,5374,5375,5378],{},"On the C++ side, you can optionally define a\n",[150,5376,5377],{},"static constexpr const char* IOX2_TYPE_NAME"," member to specify the same\nsemantic type name.",[16,5380,5381],{},"If the semantic type name, size, and alignment match between the Rust and C++\ndefinitions, iceoryx2 will establish a connection between the processes -\nenabling zero-copy communication across language boundaries.",[5232,5383,5384,5479],{"tabs":5234},[5236,5385,5386],{"v-slot:rust":183},[178,5387,5389],{"className":382,"code":5388,"language":384,"meta":183,"style":183},"#[derive(Debug, Clone, Copy, ZeroCopySend)]\n#[type_name(TransmissionData)]\n#[repr(C)]\npub struct TransmissionData {\n    pub x: i32,\n    pub y: i32,\n    pub funky: u64,\n}\n",[150,5390,5391,5412,5421,5429,5439,5451,5463,5475],{"__ignoreMap":183},[187,5392,5393,5395,5397,5399,5401,5403,5405,5407,5410],{"class":189,"line":190},[187,5394,2841],{"class":410},[187,5396,2844],{"class":193},[187,5398,535],{"class":410},[187,5400,5253],{"class":193},[187,5402,535],{"class":410},[187,5404,5258],{"class":193},[187,5406,535],{"class":410},[187,5408,5409],{"class":193},"ZeroCopySend",[187,5411,2852],{"class":410},[187,5413,5414,5417,5419],{"class":189,"line":217},[187,5415,5416],{"class":410},"#[type_name(",[187,5418,5229],{"class":193},[187,5420,2852],{"class":410},[187,5422,5423,5425,5427],{"class":189,"line":229},[187,5424,2857],{"class":410},[187,5426,2860],{"class":193},[187,5428,2852],{"class":410},[187,5430,5431,5433,5435,5437],{"class":189,"line":236},[187,5432,2867],{"class":391},[187,5434,2870],{"class":391},[187,5436,5277],{"class":193},[187,5438,1218],{"class":410},[187,5440,5441,5443,5445,5447,5449],{"class":189,"line":243},[187,5442,5284],{"class":391},[187,5444,5287],{"class":410},[187,5446,398],{"class":391},[187,5448,5292],{"class":193},[187,5450,2827],{"class":410},[187,5452,5453,5455,5457,5459,5461],{"class":189,"line":260},[187,5454,5284],{"class":391},[187,5456,5301],{"class":410},[187,5458,398],{"class":391},[187,5460,5292],{"class":193},[187,5462,2827],{"class":410},[187,5464,5465,5467,5469,5471,5473],{"class":189,"line":270},[187,5466,5284],{"class":391},[187,5468,5314],{"class":410},[187,5470,398],{"class":391},[187,5472,401],{"class":193},[187,5474,2827],{"class":410},[187,5476,5477],{"class":189,"line":276},[187,5478,1246],{"class":410},[5236,5480,5481],{"v-slot:cpp":183},[178,5482,5484],{"className":5329,"code":5483,"language":3606,"meta":183,"style":183},"struct TransmissionData {\n    static constexpr const char*\n        IOX2_TYPE_NAME = \"TransmissionData\";\n    int32_t x;\n    int32_t y;\n    uint64_t funky;\n}\n",[150,5485,5486,5494,5508,5520,5526,5532,5538],{"__ignoreMap":183},[187,5487,5488,5490,5492],{"class":189,"line":190},[187,5489,5337],{"class":391},[187,5491,5277],{"class":193},[187,5493,1218],{"class":410},[187,5495,5496,5499,5502,5505],{"class":189,"line":217},[187,5497,5498],{"class":391},"    static",[187,5500,5501],{"class":391}," constexpr",[187,5503,5504],{"class":391}," const",[187,5506,5507],{"class":391}," char*\n",[187,5509,5510,5513,5515,5518],{"class":189,"line":229},[187,5511,5512],{"class":410},"        IOX2_TYPE_NAME ",[187,5514,444],{"class":391},[187,5516,5517],{"class":197}," \"TransmissionData\"",[187,5519,411],{"class":410},[187,5521,5522,5524],{"class":189,"line":236},[187,5523,5346],{"class":391},[187,5525,5349],{"class":410},[187,5527,5528,5530],{"class":189,"line":243},[187,5529,5346],{"class":391},[187,5531,5356],{"class":410},[187,5533,5534,5536],{"class":189,"line":260},[187,5535,5361],{"class":391},[187,5537,5364],{"class":410},[187,5539,5540],{"class":189,"line":270},[187,5541,1246],{"class":410},[16,5543,3632,5544,5549],{},[26,5545,5548],{"href":5546,"rel":5547},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/publish_subscribe_cross_language",[30],"publish subscribe cross-language example","\nto see a zero-copy inter-process communication between C, C++ and Rust in\naction - without the need for serialization.",[5158,5551,5553],{"id":5552},"outlook","Outlook",[16,5555,5556],{},"Following this release, we’ll begin working on the Python language bindings.\nOur goal is to offer the same cross-language functionality - enabling\nzero-copy communication between C, C++, Rust, and Python. This communication\nshall remain serialization-free as long as the user ensures the memory layout\nis identical across all languages.",[16,5558,5559],{},"However, as payloads become more complex than simple integers, maintaining\ncompatible layouts becomes more challenging. To address this, we plan to\nintroduce container types in Rust and C++ that are guaranteed to have\nthe same memory layout, allowing us to share data without serialization.",[16,5561,5562],{},"Another concern is that checking only the type name, size, and alignment of a\npayload may not be sufficient. For example, consider this Rust struct after a\nrefactoring:",[178,5564,5566],{"className":382,"code":5565,"language":384,"meta":183,"style":183},"#[derive(Debug, Clone, Copy, ZeroCopySend)]\n#[type_name(TransmissionData)]\n#[repr(C)]\npub struct TransmissionData {\n    pub y: i32,\n    pub x: i32,\n    pub funky: u64,\n}\n",[150,5567,5568,5588,5596,5604,5614,5626,5638,5650],{"__ignoreMap":183},[187,5569,5570,5572,5574,5576,5578,5580,5582,5584,5586],{"class":189,"line":190},[187,5571,2841],{"class":410},[187,5573,2844],{"class":193},[187,5575,535],{"class":410},[187,5577,5253],{"class":193},[187,5579,535],{"class":410},[187,5581,5258],{"class":193},[187,5583,535],{"class":410},[187,5585,5409],{"class":193},[187,5587,2852],{"class":410},[187,5589,5590,5592,5594],{"class":189,"line":217},[187,5591,5416],{"class":410},[187,5593,5229],{"class":193},[187,5595,2852],{"class":410},[187,5597,5598,5600,5602],{"class":189,"line":229},[187,5599,2857],{"class":410},[187,5601,2860],{"class":193},[187,5603,2852],{"class":410},[187,5605,5606,5608,5610,5612],{"class":189,"line":236},[187,5607,2867],{"class":391},[187,5609,2870],{"class":391},[187,5611,5277],{"class":193},[187,5613,1218],{"class":410},[187,5615,5616,5618,5620,5622,5624],{"class":189,"line":243},[187,5617,5284],{"class":391},[187,5619,5301],{"class":410},[187,5621,398],{"class":391},[187,5623,5292],{"class":193},[187,5625,2827],{"class":410},[187,5627,5628,5630,5632,5634,5636],{"class":189,"line":260},[187,5629,5284],{"class":391},[187,5631,5287],{"class":410},[187,5633,398],{"class":391},[187,5635,5292],{"class":193},[187,5637,2827],{"class":410},[187,5639,5640,5642,5644,5646,5648],{"class":189,"line":270},[187,5641,5284],{"class":391},[187,5643,5314],{"class":410},[187,5645,398],{"class":391},[187,5647,401],{"class":193},[187,5649,2827],{"class":410},[187,5651,5652],{"class":189,"line":276},[187,5653,1246],{"class":410},[16,5655,5656],{},"Even though the size and alignment remain unchanged, the internal structure no\nlonger matches the original, which could lead to subtle bugs. That’s why, in\nthe long term, we aim to support interface descriptions of payloads. These\ndescriptions will be stored within the iceoryx2 service and are used for\nverifying the structural compatibility across languages.",[4448,5658,5135],{"id":5659},"command-line-client",[16,5661,5662,5663,5666],{},"If you want to debug your iceoryx2 system, list all running services, inspect\ninternal details, or monitor system health, the ",[150,5664,5665],{},"iceoryx2-cli"," tool now makes it\npossible.",[16,5668,5669],{},"You can install it using:",[178,5671,5673],{"className":180,"code":5672,"language":182,"meta":183,"style":183},"cargo install iceoryx2-cli\n",[150,5674,5675],{"__ignoreMap":183},[187,5676,5677,5679,5682],{"class":189,"line":190},[187,5678,194],{"class":193},[187,5680,5681],{"class":197}," install",[187,5683,5684],{"class":197}," iceoryx2-cli\n",[16,5686,5687,5688,5690],{},"Once installed, ",[150,5689,3464],{}," offers various commands to help you to:",[20,5692,5693,5696,5699],{},[23,5694,5695],{},"Generate a default configuration file",[23,5697,5698],{},"List all nodes or inspect details of a specific node",[23,5700,5701],{},"List all services or view detailed configurations of a specific service",[16,5703,5704,5705,5708],{},"Run ",[150,5706,5707],{},"iox2 --help"," to explore all available options.",[16,5710,5711],{},"A particularly useful feature is customizable output formatting. This allows\neasy integration into other tools and pipelines. Currently, JSON, RON, and\nYAML are supported.",[16,5713,5714],{},"For example, to view all active nodes in your system:",[178,5716,5718],{"className":180,"code":5717,"language":182,"meta":183,"style":183},"iox2 node list\n",[150,5719,5720],{"__ignoreMap":183},[187,5721,5722,5724,5727],{"class":189,"line":190},[187,5723,3464],{"class":193},[187,5725,5726],{"class":197}," node",[187,5728,5729],{"class":197}," list\n",[16,5731,5732],{},"might output:",[178,5734,5738],{"className":5735,"code":5736,"language":5737,"meta":183,"style":183},"language-ron shiki shiki-themes github-light github-dark","(\nnum: 1,\ndetails: [\n    (\n        state: Alive,\n        id: (\"0000000020c8e30b6827192d0000e55e\"),\n        pid: 58718,\n        executable: Some(\"request_response_client\"),\n        name: Some(\"\"),\n    ),\n],\n)\n","ron",[150,5739,5740,5744,5749,5754,5759,5764,5769,5774,5779,5784,5789,5794],{"__ignoreMap":183},[187,5741,5742],{"class":189,"line":190},[187,5743,1760],{},[187,5745,5746],{"class":189,"line":217},[187,5747,5748],{},"num: 1,\n",[187,5750,5751],{"class":189,"line":229},[187,5752,5753],{},"details: [\n",[187,5755,5756],{"class":189,"line":236},[187,5757,5758],{},"    (\n",[187,5760,5761],{"class":189,"line":243},[187,5762,5763],{},"        state: Alive,\n",[187,5765,5766],{"class":189,"line":260},[187,5767,5768],{},"        id: (\"0000000020c8e30b6827192d0000e55e\"),\n",[187,5770,5771],{"class":189,"line":270},[187,5772,5773],{},"        pid: 58718,\n",[187,5775,5776],{"class":189,"line":276},[187,5777,5778],{},"        executable: Some(\"request_response_client\"),\n",[187,5780,5781],{"class":189,"line":281},[187,5782,5783],{},"        name: Some(\"\"),\n",[187,5785,5786],{"class":189,"line":298},[187,5787,5788],{},"    ),\n",[187,5790,5791],{"class":189,"line":308},[187,5792,5793],{},"],\n",[187,5795,5796],{"class":189,"line":314},[187,5797,479],{},[16,5799,5800],{},"To inspect a specific node's details:",[178,5802,5804],{"className":180,"code":5803,"language":182,"meta":183,"style":183},"iox2 node details 0000000020c8e30b6827192d0000e55e\n",[150,5805,5806],{"__ignoreMap":183},[187,5807,5808,5810,5812,5815],{"class":189,"line":190},[187,5809,3464],{"class":193},[187,5811,5726],{"class":197},[187,5813,5814],{"class":197}," details",[187,5816,5817],{"class":197}," 0000000020c8e30b6827192d0000e55e\n",[16,5819,5820],{},"Similarly, you can list all active services:",[178,5822,5824],{"className":180,"code":5823,"language":182,"meta":183,"style":183},"iox2 service list\n",[150,5825,5826],{"__ignoreMap":183},[187,5827,5828,5830,5832],{"class":189,"line":190},[187,5829,3464],{"class":193},[187,5831,1433],{"class":197},[187,5833,5729],{"class":197},[16,5835,5836],{},"Sample output:",[178,5838,5840],{"className":5735,"code":5839,"language":5737,"meta":183,"style":183},"[\nPublishSubscribe(\"My/Funk/ServiceName\"),\nRequestResponse(\"My/Funk/ServiceName\"),\nEvent(\"MyEventName\"),\n]\n",[150,5841,5842,5847,5852,5857,5862],{"__ignoreMap":183},[187,5843,5844],{"class":189,"line":190},[187,5845,5846],{},"[\n",[187,5848,5849],{"class":189,"line":217},[187,5850,5851],{},"PublishSubscribe(\"My/Funk/ServiceName\"),\n",[187,5853,5854],{"class":189,"line":229},[187,5855,5856],{},"RequestResponse(\"My/Funk/ServiceName\"),\n",[187,5858,5859],{"class":189,"line":236},[187,5860,5861],{},"Event(\"MyEventName\"),\n",[187,5863,5864],{"class":189,"line":243},[187,5865,5866],{},"]\n",[16,5868,5869],{},"To view the full configuration of a particular service:",[178,5871,5873],{"className":180,"code":5872,"language":182,"meta":183,"style":183},"iox2 service details MyEventName\n",[150,5874,5875],{"__ignoreMap":183},[187,5876,5877,5879,5881,5883],{"class":189,"line":190},[187,5878,3464],{"class":193},[187,5880,1433],{"class":197},[187,5882,5814],{"class":197},[187,5884,5885],{"class":197}," MyEventName\n",[4448,5887,5889],{"id":5888},"microservice-architecture-and-built-in-services","Microservice Architecture and Built-In Services",[16,5891,5892],{},"A core goal of iceoryx2 is to support deployment in microservice-style\narchitectures. This release introduces the first service of this kind: the\n\"service discovery\" service.",[16,5894,5895],{},"We plan to organize these services in two components:",[20,5897,5898,5905],{},[23,5899,5900,5901,5904],{},"Library component (",[150,5902,5903],{},"iceoryx2-services-**","), which can be embedded into\nyour existing application process",[23,5906,5907,5908,5911],{},"Binary tool (",[150,5909,5910],{},"iox2 **","), which can be run as a stand-alone process to\naugment your system",[16,5913,3679,5914,5919],{},[26,5915,5918],{"href":5916,"rel":5917},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/discovery_service",[30],"discovery service example","\ndemonstrates how to integrate it into your own application. If you’d rather\nrun the service as a standalone process, simply execute:",[178,5921,5923],{"className":180,"code":5922,"language":182,"meta":183,"style":183},"iox2 service discovery\n",[150,5924,5925],{"__ignoreMap":183},[187,5926,5927,5929,5931],{"class":189,"line":190},[187,5928,3464],{"class":193},[187,5930,1433],{"class":197},[187,5932,5933],{"class":197}," discovery\n",[16,5935,5936],{},"This \"service discovery\" service lays the groundwork for upcoming features like\nnetwork gateways and tunnels. The vision is to enable out-of-the-box\ncommunication between iceoryx2 instances across different machines - or even\nbetween native and remote instances - by simply launching a gateway process.",[4448,5938,5409],{"id":5939},"zerocopysend",[16,5941,5942],{},"True zero-copy communication requires that data is produced directly into\nshared memory. With iceoryx2, this means loaning an uninitialized sample,\npassing it to your data-producing function, and then sending it out - without\nany intermediate copying.",[16,5944,5945],{},"However, for this to work, the data must be compatible with shared memory so\nthat it can be safely interpreted by receiving processes. This means it must\nbe:",[20,5947,5948,5954,5960],{},[23,5949,5950,5953],{},[72,5951,5952],{},"Self-contained"," — no use of raw pointers",[23,5955,5956,5959],{},[72,5957,5958],{},"Uniformly represented in memory"," — no layout ambiguities",[23,5961,5962],{},[72,5963,5964],{},"Trivially destructible",[16,5966,5967],{},"Every process has its own memory address space. A pointer to a shared memory\nsegment in one process may point to something entirely unrelated or invalid in\nanother. Even worse, if the pointer refers to heap memory that only exists in\nthe sender’s process, dereferencing it in the receiver causes undefined\nbehavior.",[16,5969,5970,5971,5974,5975,5977],{},"Uniform memory representation is equally critical. Because shared memory is\ninterpreted directly across processes, any mismatch in field layout or\nalignment can lead to corruption or undefined behavior. This is particularly\nrelevant in Rust, where the compiler may reorder struct fields unless\nexplicitly instructed not to. That’s why all payload types must use\n",[150,5972,5973],{},"#[repr(C)]"," to ensure a predictable, ",[150,5976,2860],{},"-compatible layout.",[16,5979,5980,5981,5983,5984,5986,5987,4926,5990,5992,5993,5996],{},"To make this safer and easier in Rust, we introduced the ",[150,5982,5409],{}," trait,\nalong with a derive macro. It verifies at compile time that your type satisfies\nall the necessary constraints. Forget to add ",[150,5985,5973],{},"? Accidentally use a\n",[150,5988,5989],{},"String",[150,5991,2758],{},"? The compiler will catch it. Just annotate your struct with\n",[150,5994,5995],{},"#[derive(ZeroCopySend)]"," and let the macro guide you.",[16,5998,5999,6000,4926,6002,6004],{},"If you do need complex types like ",[150,6001,5989],{},[150,6003,2758],{},", take a look at these\nexamples using custom base library types:",[20,6006,6007,6014],{},[23,6008,6009],{},[26,6010,6013],{"href":6011,"rel":6012},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/cxx/complex_data_types",[30],"C++ complex data types example",[23,6015,6016,467],{},[26,6017,6020],{"href":6018,"rel":6019},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/complex_data_types",[30],"Rust complex data types example",[16,6022,6023,6024,6026],{},"Currently, the ",[150,6025,5409],{}," trait is only available in Rust. We'll see what\nwe can come up with for C and C++ in the future.",[4448,6028,5153],{"id":6029},"other-feature-highlights",[16,6031,6032,6035],{},[72,6033,6034],{},"Event services now support a deadline property",", which defines the maximum\nduration within which at least one notification must be received. If a listener\nport using this feature is attached as a deadline to a waitset\n(our event multiplexer), the waitset will wake up with an error if no\nnotification arrives before the deadline expires.",[16,6037,6038,6039,6043],{},"See the\n",[26,6040,6042],{"href":4444,"rel":6041},[30],"health monitoring example subscriber","\nfor a practical use case.",[16,6045,6046,6049],{},[72,6047,6048],{},"The iceoryx2 configuration file now follows the XDG directory specification.","\nThe search order is:",[2286,6051,6052,6058,6063],{},[23,6053,6054,6057],{},[150,6055,6056],{},"config/iceoryx2.toml"," in the current project directory",[23,6059,6060],{},[150,6061,6062],{},"$HOME/.config/iceoryx2/iceoryx2.toml",[23,6064,6065],{},[150,6066,6067],{},"/etc/iceoryx2/iceoryx2.toml",[16,6069,6070,6073,6074,6077],{},[72,6071,6072],{},"Cross-compiling iceoryx2 on Linux is now easier",", thanks to a new platform\nabstraction based on the ",[150,6075,6076],{},"libc"," crate. This significantly simplifies builds for\nenvironments like Yocto.",[178,6079,6081],{"className":180,"code":6080,"language":182,"meta":183,"style":183},"cargo build --features libc_platform\n",[150,6082,6083],{"__ignoreMap":183},[187,6084,6085,6087,6090,6093],{"class":189,"line":190},[187,6086,194],{"class":193},[187,6088,6089],{"class":197}," build",[187,6091,6092],{"class":201}," --features",[187,6094,6095],{"class":197}," libc_platform\n",[113,6097,6099],{"id":6098},"roadmap-whats-next","Roadmap: What’s Next?",[16,6101,6102,6103,6107],{},"Stay up to date with our ongoing progress by checking out the\n",[26,6104,6106],{"href":3186,"rel":6105},[30],"iceoryx2 Roadmap",".\nPlease note that this is a best-effort plan and may change on short notice. If\nyou need a specific feature or have time-critical requirements, feel free to\nreach out to us.",[20,6109,6110,6116,6122,6125,6128,6134],{},[23,6111,6112,6115],{},[150,6113,6114],{},"no_std"," support for embedded and bare-metal use cases",[23,6117,6118,6119],{},"Support for embedded platforms such as VxWorks and QNX ",[150,6120,6121],{},"**",[23,6123,6124],{},"Blackboard Messaging Pattern",[23,6126,6127],{},"Python language bindings",[23,6129,6130,6131],{},"Network communication via ",[72,6132,6133],{},"Zenoh",[23,6135,6136],{},"(Moonshot) Go language bindings",[16,6138,6139,6141],{},[150,6140,6121],{}," The availability of open-source support for QNX and VxWorks depends on\nacquiring free licenses to run these targets in our CI pipeline.",[113,6143,6145],{"id":6144},"thank-you","Thank You",[16,6147,6148],{},"We want to thank our community. Your ideas, discussions, and collaborative\nspirit help shape iceoryx2 every day. Even frustrating bugs become less painful\nwhen tackled with humor and openness.",[16,6150,6151],{},"And finally, a big thank you to our customers who share our vision:",[16,6153,6154],{},[72,6155,6156],{},"To create an open-source, certifiable base and communication library that can\nbe trusted in mission-critical systems.",[1271,6158,6159],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":183,"searchDepth":217,"depth":217,"links":6161},[6162,6163,6164,6165],{"id":2219,"depth":229,"text":2220},{"id":5106,"depth":229,"text":5107},{"id":6098,"depth":229,"text":6099},{"id":6144,"depth":229,"text":6145},"2025-05-17T00:00:00.000Z","Announcing the release of iceoryx2 version 0.6.0 introducing the request-response stream pattern and zero-copy cross-language communication.",{},"/blog/iceoryx2-0-6-release",{"title":5043,"description":6167},"blog/iceoryx2-0-6-release",[1295,3224,384,3606,3607],"cgkYBUJQtSsZvpz_jCTpF2sURD_q3ry7dwDi5jmPxwE",{"id":6175,"title":6176,"author":7,"body":6177,"date":6814,"description":6815,"extension":1287,"featured":1288,"image":1289,"meta":6816,"navigation":239,"path":6817,"seo":6818,"stem":6819,"tags":6820,"__hash__":6822},"blog/blog/iceoryx2-0-7-release.md","Announcing iceoryx2 v0.7.0",{"type":9,"value":6178,"toc":6808},[6179,6182,6185,6188,6190,6195,6198,6201,6206,6209,6213,6216,6225,6231,6243,6291,6294,6302,6309,6315,6318,6326,6340,6343,6372,6375,6378,6385,6408,6411,6418,6421,6427,6430,6436,6439,6456,6459,6499,6508,6511,6520,6523,6539,6545,6574,6581,6597,6600,6625,6632,6635,6638,6645,6658,6666,6671,6674,6682,6688,6695,6697,6716,6726,6738,6740,6745,6763,6765,6767,6770,6772,6776,6805],[12,6180,6176],{"id":6181},"announcing-iceoryx2-v070",[16,6183,6184],{},"Christian Eltzschig - 13/09/2025",[2257,6186],{"src":3239,"alt":3240,"className":6187},[3242,2263],[113,6189,2220],{"id":2219},[16,6191,6192,6194],{},[72,6193,1295],{}," is a service-based communication library\ndesigned to build robust and efficient decentralized systems. It enables\nultra low-latency communication between processes — similar to Unix domain\nsockets or message queues, but significantly faster and easier to use.",[16,6196,6197],{},"It includes language bindings for C, C++, Python, and Rust and it runs on\nLinux, macOS, Windows, FreeBSD and QNX.",[16,6199,6200],{},"iceoryx2 supports messaging patterns such as publish-subscribe, events,\nrequest-response stream and the introduced blackboard pattern - a key-value\nrepository in shared memory. It is robust and\ncomes with a decentralized architecture without the need for a central broker.",[16,6202,3632,6203,3636],{},[26,6204,175],{"href":173,"rel":6205},[30],[2257,6207],{"src":3639,"alt":3377,"className":6208},[3242,2263],[113,6210,6212],{"id":6211},"release-v070","Release v0.7.0",[16,6214,6215],{},"With the new v0.7.0 release of iceoryx2, we’re adding full Python bindings and a\nnetwork tunnel. That means you can now send data not just between processes on\nthe same machine, but also across hosts - iceoryx2 handles the communication\ndetails for you.",[16,6217,6218,6219,6224],{},"We’ve also finished the first version of the\n",[26,6220,6223],{"href":6221,"rel":6222},"https://ekxide.github.io/iceoryx2-book/main/",[30],"iceoryx2 Book",",\nwhich not only helps you get started quickly but also provides deep background\non the overall architecture.",[16,6226,6227,6228,6230],{},"Debugging, introspection, and record-and-replay of data are now possible with\nthe command-line client. On top of that, we’ve introduced a new messaging\npattern called ",[72,6229,74],{},", a key-value repository in shared memory.",[16,6232,6233,6234,6237,6238],{},"And one more thing: iceoryx2 now runs on ",[72,6235,6236],{},"QNX 7.1",".\nThere are plenty of smaller enhancements too. Check out the full release notes\nhere:\n",[26,6239,6242],{"href":6240,"rel":6241},"https://github.com/eclipse-iceoryx/iceoryx2/releases/tag/v0.7.0",[30],"iceoryx2 v0.7.0 release",[20,6244,6245,6251,6257,6263,6269,6275,6281,6287],{},[23,6246,6247],{},[26,6248,6250],{"href":6249},"#the-iceoryx2-book","The iceoryx2 Book",[23,6252,6253],{},[26,6254,6256],{"href":6255},"#python-language-bindings","Python Language Bindings",[23,6258,6259],{},[26,6260,6262],{"href":6261},"#network-communication","Network Communication",[23,6264,6265],{},[26,6266,6268],{"href":6267},"#command-line-client-debugging-and-introspection","Command Line Client: Debugging And Introspection",[23,6270,6271],{},[26,6272,6274],{"href":6273},"#record-and-replay","Record And Replay",[23,6276,6277],{},[26,6278,6280],{"href":6279},"#messaging-pattern-blackboard","Messaging Pattern: Blackboard",[23,6282,6283],{},[26,6284,6286],{"href":6285},"#new-supported-platforms","New Supported Platforms",[23,6288,6289],{},[26,6290,5153],{"href":5152},[4448,6292,6250],{"id":6293},"the-iceoryx2-book",[16,6295,6296,6297,6301],{},"We’ve put effort into the\n",[26,6298,6300],{"href":6221,"rel":6299},[30],"iceoryx2 book",",\nwhich serves as a starting point for every user. Whether you’re looking for a\nquick introduction, a getting-started tutorial, or a deeper dive into the\narchitecture of iceoryx2.",[16,6303,6304,6305],{},"If you’d like to contribute, by writing an article, creating a tutorial on a\nspecific topic, or reporting an issue, we’d be glad to receive your pull request:\n",[26,6306,6307],{"href":6307,"rel":6308},"https://github.com/ekxide/iceoryx2-book",[30],[16,6310,6311,6314],{},[72,6312,6313],{},"Remark:"," The iceoryx2 book replaces the previous ReadTheDocs documentation\nand provides references for C, C++, Python, and Rust.",[4448,6316,6256],{"id":6317},"python-language-bindings",[16,6319,6320,6321,467],{},"We’ve ported the iceoryx2 API to Python and added an extensive set of\n",[26,6322,6325],{"href":6323,"rel":6324},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/python",[30],"examples on GitHub",[16,6327,6328,6329,6333,6334,6339],{},"If you’re new to iceoryx2, start with the ",[6330,6331,6332],"em",{},"Getting Started"," tutorial\n",[26,6335,6338],{"href":6336,"rel":6337},"https://ekxide.github.io/iceoryx2-book/main/getting-started/robot-nervous-system/index.html",[30],"A Robot Nervous System","\nin the iceoryx2 book. It walks through all\nthe major features across every supported language. You can switch between\nlanguages while reading, which makes it easy to build complex systems that mix\nPython, C, C++, and Rust - without paying the serialization overhead.",[16,6341,6342],{},"A highlight is the publish–subscribe cross-language example, where Python, C,\nC++, and Rust processes exchange data directly in shared memory. Check it out:",[20,6344,6345,6352,6359,6366],{},[23,6346,6347],{},[26,6348,6351],{"href":6349,"rel":6350},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/python/publish_subscribe_cross_language",[30],"Python Publish–Subscribe Cross-Language",[23,6353,6354],{},[26,6355,6358],{"href":6356,"rel":6357},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/c/publish_subscribe_cross_language",[30],"C Publish–Subscribe Cross-Language",[23,6360,6361],{},[26,6362,6365],{"href":6363,"rel":6364},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/cxx/publish_subscribe_cross_language",[30],"C++ Publish–Subscribe Cross-Language",[23,6367,6368],{},[26,6369,6371],{"href":5546,"rel":6370},[30],"Rust Publish–Subscribe Cross-Language",[16,6373,6374],{},"And this isn’t limited to publish-subscribe, the same zero-copy, cross-language\ncommunication works with all messaging patterns, including request–response and\nevents.",[4448,6376,6262],{"id":6377},"network-communication",[16,6379,6380,6381,6384],{},"Until now, iceoryx2 focused on inter-process communication. With the new\n",[72,6382,6383],{},"network tunnel",", you can communicate between hosts as well. No complicated\nsetup, no configuration headaches, just run the CLI:",[178,6386,6388],{"className":180,"code":6387,"language":182,"meta":183,"style":183},"cargo install iceoryx2-cli\niox2 tunnel zenoh\n",[150,6389,6390,6398],{"__ignoreMap":183},[187,6391,6392,6394,6396],{"class":189,"line":190},[187,6393,194],{"class":193},[187,6395,5681],{"class":197},[187,6397,5684],{"class":197},[187,6399,6400,6402,6405],{"class":189,"line":217},[187,6401,3464],{"class":193},[187,6403,6404],{"class":197}," tunnel",[187,6406,6407],{"class":197}," zenoh\n",[16,6409,6410],{},"Do that on each host, and your publish–subscribe and event communication is\ninstantly available across machines.",[16,6412,6413,6414,6417],{},"The network tunnel, that connects iceoryx2 instances across the network, is\nstill in development, so some patterns, like request–response and\nblackboard, aren’t supported yet. But it’s also the first step toward a full\n",[72,6415,6416],{},"gateway",": the idea is that you’ll use the native iceoryx2 API while the\ngateway connects to other protocols in the background.",[16,6419,6420],{},"Picture this: you start a gRPC, MQTT, or DDS gateway, and suddenly\nyour iceoryx2 application can talk to anything, or let others talk to you,\nwithout changing a single line of code.",[16,6422,6423,6424,467],{},"That’s the vision. And with the tunnel, you can already connect iceoryx2\napplications across hosts today by just running ",[150,6425,6426],{},"iox2 tunnel zenoh",[4448,6428,6268],{"id":6429},"command-line-client-debugging-and-introspection",[16,6431,6432,6433,6435],{},"We are continuously improving the ",[150,6434,3464],{}," command-line client to make it a\nversatile tool for working with iceoryx2. It allows direct interaction with\niceoryx2 from the shell, which is especially useful for debugging.",[16,6437,6438],{},"Let’s start with events. Open two terminals and run the listener example in one\nof them:",[178,6440,6442],{"className":180,"code":6441,"language":182,"meta":183,"style":183},"cargo run --example event_listener\n",[150,6443,6444],{"__ignoreMap":183},[187,6445,6446,6448,6450,6453],{"class":189,"line":190},[187,6447,194],{"class":193},[187,6449,198],{"class":197},[187,6451,6452],{"class":201}," --example",[187,6454,6455],{"class":197}," event_listener\n",[16,6457,6458],{},"Now you can send event notifications to this process and wake it up explicitly:",[178,6460,6462],{"className":180,"code":6461,"language":182,"meta":183,"style":183},"cargo install iceoryx2-cli\niox2 service notify --event-id 1 --num 2 --interval-in-ms 1500 MyEventName\n",[150,6463,6464,6472],{"__ignoreMap":183},[187,6465,6466,6468,6470],{"class":189,"line":190},[187,6467,194],{"class":193},[187,6469,5681],{"class":197},[187,6471,5684],{"class":197},[187,6473,6474,6476,6478,6481,6484,6486,6489,6491,6494,6497],{"class":189,"line":217},[187,6475,3464],{"class":193},[187,6477,1433],{"class":197},[187,6479,6480],{"class":197}," notify",[187,6482,6483],{"class":201}," --event-id",[187,6485,407],{"class":201},[187,6487,6488],{"class":201}," --num",[187,6490,427],{"class":201},[187,6492,6493],{"class":201}," --interval-in-ms",[187,6495,6496],{"class":201}," 1500",[187,6498,5885],{"class":197},[16,6500,6501,6502,6507],{},"You can also wait for events directly on the command line, or send and receive\npublish-subscribe samples. More details and examples can be found in the\n",[26,6503,6506],{"href":6504,"rel":6505},"https://ekxide.github.io/iceoryx2-book/main/getting-started/robot-nervous-system/command-line-tools-and-debugging.html",[30],"getting started article on the command line","\nin the iceoryx2 book.",[4448,6509,6274],{"id":6510},"record-and-replay",[16,6512,78,6513,6515,6516,6519],{},[150,6514,3464],{}," command-line client also supports ",[72,6517,6518],{},"record and replay",". This is\nuseful when you want to capture real data and feed it back into the system\nduring development - for example, creating an endlessly repeating stream of\nsensor data.",[16,6521,6522],{},"Let’s walk through it with the publish-subscribe example. Start the publisher in\none terminal:",[178,6524,6526],{"className":180,"code":6525,"language":182,"meta":183,"style":183},"cargo run --example publish_subscribe_publisher\n",[150,6527,6528],{"__ignoreMap":183},[187,6529,6530,6532,6534,6536],{"class":189,"line":190},[187,6531,194],{"class":193},[187,6533,198],{"class":197},[187,6535,6452],{"class":201},[187,6537,6538],{"class":197}," publish_subscribe_publisher\n",[16,6540,6541,6542,398],{},"In another terminal, record the data for 10 seconds and write it to\n",[150,6543,6544],{},"record.dat",[178,6546,6548],{"className":180,"code":6547,"language":182,"meta":183,"style":183},"iox2 service record --timeout-in-sec 10 --output record.dat \"My/Funk/ServiceName\"\n",[150,6549,6550],{"__ignoreMap":183},[187,6551,6552,6554,6556,6559,6562,6565,6568,6571],{"class":189,"line":190},[187,6553,3464],{"class":193},[187,6555,1433],{"class":197},[187,6557,6558],{"class":197}," record",[187,6560,6561],{"class":201}," --timeout-in-sec",[187,6563,6564],{"class":201}," 10",[187,6566,6567],{"class":201}," --output",[187,6569,6570],{"class":197}," record.dat",[187,6572,6573],{"class":197}," \"My/Funk/ServiceName\"\n",[16,6575,6576,6577,6580],{},"The output file is human-readable by default.\n",[72,6578,6579],{},"Tip:"," Payloads are stored in hex. This makes it easy to edit them manually\nand then inject modified data back into the system to test edge cases.\nNext, stop the publisher and start the subscriber:",[178,6582,6584],{"className":180,"code":6583,"language":182,"meta":183,"style":183},"cargo run --example publish_subscribe_subscriber\n",[150,6585,6586],{"__ignoreMap":183},[187,6587,6588,6590,6592,6594],{"class":189,"line":190},[187,6589,194],{"class":193},[187,6591,198],{"class":197},[187,6593,6452],{"class":201},[187,6595,6596],{"class":197}," publish_subscribe_subscriber\n",[16,6598,6599],{},"Now replay the recording twice:",[178,6601,6603],{"className":180,"code":6602,"language":182,"meta":183,"style":183},"iox2 service replay --input record.dat --repetitions 2\n",[150,6604,6605],{"__ignoreMap":183},[187,6606,6607,6609,6611,6614,6617,6619,6622],{"class":189,"line":190},[187,6608,3464],{"class":193},[187,6610,1433],{"class":197},[187,6612,6613],{"class":197}," replay",[187,6615,6616],{"class":201}," --input",[187,6618,6570],{"class":197},[187,6620,6621],{"class":201}," --repetitions",[187,6623,6624],{"class":201}," 2\n",[16,6626,6627,6628,6507],{},"A more detailed walkthrough is available in the\n",[26,6629,6506],{"href":6630,"rel":6631},"https://ekxide.github.io/iceoryx2-book/main/getting-started/robot-nervous-system/command-line-tools-and-debugging.html#recording-and-replaying-data",[30],[4448,6633,6280],{"id":6634},"messaging-pattern-blackboard",[16,6636,6637],{},"The publish-subscribe pattern can reach its limits when a single publisher needs\nto serve hundreds or even thousands of subscribers. This often happens when the\nsystem requires a global state - for example, in a simulation where every\nentity’s position and movement must be tracked, or when maintaining a global\nconfiguration across multiple components.",[16,6639,6640,6641,6644],{},"With the newly introduced ",[72,6642,6643],{},"blackboard messaging pattern",", iceoryx2 provides a\nshared-memory key-value repository that every process can access efficiently. A\nsingle process can maintain the global state in a thread-safe way, while all\nothers can read it without overhead.",[16,6646,6647,6648,6653,6654,467],{},"The iceoryx2 book contains a\n",[26,6649,6652],{"href":6650,"rel":6651},"https://ekxide.github.io/iceoryx2-book/main/getting-started/robot-nervous-system/blackboard.html",[30],"getting started article on the blackboard",",\nand you can also explore some hands-on code in the\n",[26,6655,6657],{"href":799,"rel":6656},[30],"examples folder on GitHub",[16,6659,6660,6661,467],{},"For deeper background on the concept itself, see the article\n",[26,6662,6665],{"href":6663,"rel":6664},"https://ekxide.io/blog/advanced-messaging-patterns-blackboard/",[30],"Advanced Messaging Patterns – Blackboard",[16,6667,6668,6670],{},[72,6669,6313],{}," The blackboard messaging pattern is currently available only in\nRust. C, C++, and Python bindings will be added in the next release.",[4448,6672,6286],{"id":6673},"new-supported-platforms",[16,6675,6676,6677,467],{},"For Yocto users, we now provide a\n",[26,6678,6681],{"href":6679,"rel":6680},"https://github.com/eclipse-iceoryx/meta-iceoryx2",[30],"dedicated Yocto layer on GitHub",[16,6683,6684,6685,6687],{},"We have also added support for ",[72,6686,6236],{},". In the open-source repository, QNX\nis available as a tier-3 platform due to license restrictions. If you require\ntier-1 support, please reach out to us.",[16,6689,6690,6691,6694],{},"In addition, there is a ",[72,6692,6693],{},"VxWorks"," proof of concept. Contact us for details.",[4448,6696,5153],{"id":6029},[16,6698,6699,6702,6703,3921,6706,6709,6710,6715],{},[72,6700,6701],{},"Thread-safe service types","\nUntil now, iceoryx2 ports were not thread-safe, which made async use cases\ntricky. This release introduces ",[150,6704,6705],{},"ipc_threadsafe::Service",[150,6707,6708],{},"local_threadsafe::Service",". These variants are optimized for different\ncontexts, and the\n",[26,6711,6714],{"href":6712,"rel":6713},"https://github.com/eclipse-iceoryx/iceoryx2/blob/main/examples/rust/service_types/",[30],"service variant example on GitHub","\nintroduces all of them, how you can specialize them and shows how to pick the\nright one.",[16,6717,6718,6721,6722,467],{},[72,6719,6720],{},"Service discovery","\nWe added a request-response service to obtain the full list of all running\nservices in the system. The list can be kept up to date by subscribing to a\npublish-subscribe service. See the\n",[26,6723,6725],{"href":5916,"rel":6724},[30],"discovery example",[16,6727,6728,6731,6732,3921,6735,467],{},[72,6729,6730],{},"Graceful shutdown","\nClient-server connections can now be shut down gracefully while the client is\nreceiving a response stream. The API provides\n",[150,6733,6734],{},"PendingResponse::set_disconnect_hint()",[150,6736,6737],{},"ActiveRequest::has_disconnect_hint()",[113,6739,6099],{"id":6098},[16,6741,6742,467],{},[26,6743,6106],{"href":3186,"rel":6744},[30],[20,6746,6747,6752,6755,6758,6761],{},[23,6748,6749,6751],{},[150,6750,6114],{}," support for embedded use cases",[23,6753,6754],{},"Blackboard Messaging Pattern Language Bindings for C, C++ and Python",[23,6756,6757],{},"QNX 8.0",[23,6759,6760],{},"network tunnel: support for request-response and blackboard",[23,6762,6136],{},[113,6764,6145],{"id":6144},[16,6766,6148],{},[16,6768,6769],{},"Also a big thank you to the iceoryx team, which was relentless in implementing\nall those features.",[16,6771,6151],{},[16,6773,6774],{},[72,6775,6156],{},[20,6777,6778,6784,6790,6795,6800],{},[23,6779,6780],{},[26,6781,31],{"href":6782,"rel":6783},"https://www.reddit.com/r/programming/comments/1nfvdvk/announcing_iceoryx2_v07_fast_and_robust/",[30],[23,6785,6786],{},[26,6787,2622],{"href":6788,"rel":6789},"https://programming.dev/post/37369902",[30],[23,6791,6792],{},[26,6793,47],{"href":45,"rel":6794},[30],[23,6796,6797],{},[26,6798,54],{"href":52,"rel":6799},[30],[23,6801,6802],{},[26,6803,61],{"href":59,"rel":6804},[30],[1271,6806,6807],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":183,"searchDepth":217,"depth":217,"links":6809},[6810,6811,6812,6813],{"id":2219,"depth":229,"text":2220},{"id":6211,"depth":229,"text":6212},{"id":6098,"depth":229,"text":6099},{"id":6144,"depth":229,"text":6145},"2025-09-13T00:00:00.000Z","Announcing the release of iceoryx2 version 0.7.0, introducing Blackboard Messaging Pattern, new Python Bindings and network tunnel.",{},"/blog/iceoryx2-0-7-release",{"title":6176,"description":6815},"blog/iceoryx2-0-7-release",[1295,3224,384,3606,3607,6821],"python","ubD9aLHhXlRicMWIKknuVwq829XLMessEi6EM2QLhrs",{"id":6824,"title":6825,"author":7,"body":6826,"date":7191,"description":7192,"extension":1287,"featured":1288,"image":1289,"meta":7193,"navigation":239,"path":7194,"seo":7195,"stem":7196,"tags":7197,"__hash__":7199},"blog/blog/iceoryx2-0.8-release.md","Announcing iceoryx2 v0.8.0",{"type":9,"value":6827,"toc":7174},[6828,6831,6834,6852,6854,6857,6860,6863,6870,6881,6898,6902,6909,6917,6920,6952,6964,6967,6982,6985,6990,6996,6999,7002,7009,7012,7015,7018,7021,7041,7044,7047,7050,7057,7059,7062,7072,7075,7079,7082,7085,7088,7091,7104,7108,7111,7114,7120,7123,7127,7130,7133,7135,7145,7148,7150,7152,7154,7156,7160],[12,6829,6825],{"id":6830},"announcing-iceoryx2-v080",[16,6832,6833],{},"Christian Eltzschig - 23/12/2025",[6835,6836,6839],"table",{"width":6837,"height":6837,"border":6838},"100%",0,[6840,6841,6842],"tbody",{},[6843,6844,6845],"tr",{},[6846,6847,6849],"td",{"align":6848},"center",[2257,6850],{"src":3239,"alt":3240,"className":6851},[3242,2263],[108,6853,2220],{"id":2219},[16,6855,6856],{},"iceoryx2 is a communication library designed to build robust and\nefficient data-intensive systems. It enables ultra-low-latency communication\nbetween processes — comparable to Unix domain sockets or message queues, but\nsignificantly faster and easier to use.",[16,6858,6859],{},"The library provides language bindings for C, C++, Python, Rust, and C#, and\nruns on Linux, macOS, Windows, FreeBSD, and QNX, with experimental support for\nAndroid and VxWorks.",[16,6861,6862],{},"iceoryx2 supports multiple messaging patterns, including publish-subscribe,\nevents, request-response streams, and the recently introduced blackboard\npattern, a key-value repository implemented directly in shared memory. Its\narchitecture is fully decentralized and does not rely on a central broker,\nwhich improves robustness and scalability.",[16,6864,6865,6866,6869],{},"To get a better impression of the performance characteristics, check out the\n",[26,6867,175],{"href":173,"rel":6868},[30],"\nand try them on your own platform.",[6835,6871,6872],{"width":6837,"height":6837,"border":6838},[6840,6873,6874],{},[6843,6875,6876],{},[6846,6877,6878],{"align":6848},[2257,6879],{"src":3639,"alt":3377,"className":6880},[3242,2263],[20,6882,6883,6888,6893],{},[23,6884,6885],{},[26,6886,47],{"href":45,"rel":6887},[30],[23,6889,6890],{},[26,6891,54],{"href":52,"rel":6892},[30],[23,6894,6895],{},[26,6896,61],{"href":59,"rel":6897},[30],[108,6899,6901],{"id":6900},"release-v080","Release v0.8.0",[16,6903,6904,6905,6908],{},"With v0.8, we expanded the\n",[26,6906,6223],{"href":6221,"rel":6907},[30],"\nwith additional pages, deeper technical explanations, and architectural deep\ndives into the implementation of our messaging patterns.",[16,6910,6911,6912],{},"The complete list of changes is available here:\n",[26,6913,6916],{"href":6914,"rel":6915},"https://github.com/eclipse-iceoryx/iceoryx2/releases/tag/v0.8.0",[30],"iceoryx2 v0.8.0 release",[16,6918,6919],{},"This release introduces:",[20,6921,6922,6928,6936,6942,6948],{},[23,6923,6924],{},[26,6925,6927],{"href":6926},"#csharp-language-bindings","CSharp Language Bindings",[23,6929,6930],{},[26,6931,6933,6935],{"href":6932},"#no_std-and-bare-metal-support",[150,6934,6114],{}," and Bare-Metal Support",[23,6937,6938],{},[26,6939,6941],{"href":6940},"#memory-layout-compatible-data-types","Memory Layout Compatible Data Types",[23,6943,6944],{},[26,6945,6947],{"href":6946},"#android-platform-support-proof-of-concept","Android Platform Support - Proof Of Concept",[23,6949,6950],{},[26,6951,5153],{"href":5152},[16,6953,6954,6955,3921,6959,6963],{},"Alongside the open-source release, our new ekxide extensions add support for\n",[26,6956,6958],{"href":6957},"#hypervisor","hypervisor-backed shared memory",[26,6960,6962],{"href":6961},"#cross-core-communication","cross-core communication"," - enabling advanced\nmixed-criticality setups on modern SoCs from NVIDIA, Qualcomm, Renesas, TI, and\nNXP.",[113,6965,6927],{"id":6966},"csharp-language-bindings",[16,6968,6969,6970,6975,6976,6981],{},"Thanks to a community contribution by ",[26,6971,6974],{"href":6972,"rel":6973},"https://github.com/patdhlk",[30],"patdhlk",",\nwe are happy to announce the first version of C# language bindings for iceoryx2.\nThe bindings are available in the\n",[26,6977,6980],{"href":6978,"rel":6979},"https://github.com/eclipse-iceoryx/iceoryx2-csharp",[30],"iceoryx2-csharp","\nrepository on GitHub.",[16,6983,6984],{},"The current implementation already supports the Request-Response, Event, and\nPublish-Subscribe messaging patterns. This makes iceoryx2 a viable option for\nhigh-performance zero-copy inter-process communication from C#. In combination\nwith the iceoryx2 tunnel, it can also be used for distributed applications over\nthe network.",[113,6986,6988,6935],{"id":6987},"no_std-and-bare-metal-support",[150,6989,6114],{},[16,6991,6992,6993,6995],{},"With v0.8, iceoryx2 can now be built in ",[150,6994,6114],{}," environments. On\nPOSIX-compliant systems that do not provide the Rust standard library, such as\nQNX 8.0, this support is fully functional.",[16,6997,6998],{},"In addition, we have a bare-metal proof of concept running. In this environment,\ndata-flow-oriented messaging patterns such as publish-subscribe,\nrequest-response, and blackboard communication are already operational.\nEvent-based communication is not yet supported, as it requires interrupt\nhandling or a similar mechanism.",[16,7000,7001],{},"It is important to emphasize that this bare-metal support is still experimental.\nThe current memory footprint is larger than desired, and the stub platform is\nnot yet optimized for production use. Nevertheless, it demonstrates that\niceoryx2 can operate without an operating system and lays the groundwork for\nfuture improvements.",[16,7003,7004,7005],{},"More details and build instructions can be found in the documentation:\n",[26,7006,7007],{"href":7007,"rel":7008},"https://github.com/eclipse-iceoryx/iceoryx2/blob/main/doc/development-setup/nostd-builds.md",[30],[113,7010,6941],{"id":7011},"memory-layout-compatible-data-types",[16,7013,7014],{},"When communicating between processes written in different languages, such as C++\nand Rust, developers typically have to serialize data. iceoryx2 offers an\nalternative through memory-layout-compatible data types, enabling true zero-copy\ncommunication across language boundaries.",[16,7016,7017],{},"To achieve this, we implemented our own set of container and data types that are\nexplicitly designed to be safe for shared memory and to have identical memory\nlayouts in both C++ and Rust. This guarantees correctness without relying on\nfragile compiler or ABI assumptions.",[16,7019,7020],{},"We provide several examples that guide users through zero-copy inter-process\ncommunication between multiple languages, including C++, Rust, and for basic\ndata types also C and Python:",[20,7022,7023,7029,7035],{},[23,7024,7025],{},[26,7026,7027],{"href":7027,"rel":7028},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/cross_language_communication_basics",[30],[23,7030,7031],{},[26,7032,7033],{"href":7033,"rel":7034},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/cross_language_communication_container",[30],[23,7036,7037],{},[26,7038,7039],{"href":7039,"rel":7040},"https://github.com/eclipse-iceoryx/iceoryx2/tree/main/examples/rust/cross_language_communication_complex_types",[30],[113,7042,6947],{"id":7043},"android-platform-support-proof-of-concept",[16,7045,7046],{},"We have ported iceoryx2 to Android, where it can already be used within a single\nprocess to manage communication between threads. Full inter-process\ncommunication support still needs funding.",[16,7048,7049],{},"The main challenges on Android are handling the sandboxed execution environment\nand integrating the Binder IPC mechanism. Depending on the final architecture,\nthis may also involve introducing an additional daemon responsible for managing\nand distributing communication resources.",[16,7051,7052,7053],{},"If you want to experiment with the current state, the documentation is available\nhere:\n",[26,7054,7055],{"href":7055,"rel":7056},"https://github.com/eclipse-iceoryx/iceoryx2/blob/main/doc/development-setup/android.md",[30],[113,7058,5153],{"id":6029},[16,7060,7061],{},"With this release, iceoryx2 no longer depends on iceoryx classic. The hoofs\ncomponent has been fully integrated into iceoryx2, simplifying the dependency\nstructure.",[16,7063,7064,7065,7067,7068],{},"Thanks to the new ",[150,7066,6114],{}," support, QNX 8.0 is now officially supported. Setup\ninstructions are available here:\n",[26,7069,7070],{"href":7070,"rel":7071},"https://github.com/eclipse-iceoryx/iceoryx2/blob/main/doc/development-setup/qnx.md",[30],[16,7073,7074],{},"In addition, language bindings for the blackboard (the shared-memory key-value\nrepository) are now finalized and can be used from C, C++, and Python. The C#\nbindings do not support the blackboard pattern in their initial release.",[108,7076,7078],{"id":7077},"commercial-iceoryx2-extensions","Commercial iceoryx2 Extensions",[16,7080,7081],{},"ekxide follows an open-core business model. The core of iceoryx2 remains fully\nopen source, while closed-source extensions are used to finance continued\nopen-source development.",[16,7083,7084],{},"These extensions primarily target requirements found in safety-critical systems,\nsuch as additional artifacts, design documentation, or specialized features.\nThey do not impose restrictions on standard iceoryx2 users.",[16,7086,7087],{},"The iceoryx2 architecture was explicitly designed to be extensible without\nforking. Extensions can be integrated with minimal code changes, allowing users\nto adopt additional functionality incrementally.",[16,7089,7090],{},"Our first commercial extensions enable zero-copy communication across hypervisor\npartitions and between ARM A-cores and R-cores.",[6835,7092,7093],{"width":6837,"height":6837,"border":6838},[6840,7094,7095],{},[6843,7096,7097],{},[6846,7098,7099],{"align":6848},[2257,7100],{"src":7101,"alt":7102,"className":7103},"blog-images/memory-link.png","memory link",[3242,2263],[113,7105,7107],{"id":7106},"hypervisor","Hypervisor",[16,7109,7110],{},"A common safety-critical deployment scenario involves QNX as a host operating\nsystem with multiple guest systems such as Yocto or Android.\nWith our hypervisor extension, all of these environments can be connected\nusing zero-copy communication.",[16,7112,7113],{},"In most cases, application source code does not need to be modified. Only the\nservice variant must be adapted to use the hypervisor-backed shared memory\ninstead of POSIX shared memory.",[16,7115,7116,7117,467],{},"The extension is implemented generically and is intended to work across\ndifferent hardware platforms and drivers. It also supports zero-copy\ncommunication between multiple QEMU instances connected via ",[150,7118,7119],{},"ivshmem",[16,7121,7122],{},"Using the tunnel abstraction, a wide range of deployment scenarios can be\nunified under a single API. Thanks to iceoryx2’s dynamic features, this works\nwithout explicit configuration and provides a smooth migration path toward\nstatic deployments.",[113,7124,7126],{"id":7125},"cross-core-communication","Cross-Core Communication",[16,7128,7129],{},"In many safety-critical systems, real-time tasks are executed on ARM R-cores,\nwhile compute-intensive workloads run on A-cores. Efficient communication\nbetween these cores is essential.",[16,7131,7132],{},"With this release, it is now possible to run iceoryx2 on an RTOS (Real‑Time\nOperating System) such as ThreadX, AUTOSAR, or even bare‑metal and enable\nseamless true zero‑copy data transfer between A‑cores and R‑cores.",[108,7134,6099],{"id":6098},[16,7136,7137,7138,7141,7142,7144],{},"Looking ahead, we plan to provide a ",[150,7139,7140],{},"vcpkg"," package for easier deployment of\niceoryx2. We will continue improving ",[150,7143,6114],{}," support by reducing the memory\nfootprint and expanding documentation and examples.",[16,7146,7147],{},"We also aim to bring the hypervisor and A-core to R-core communication\nextensions to production-ready quality for safety-critical use cases, and to\ncontinue development of our UI tooling, Mission Control.",[108,7149,6145],{"id":6144},[16,7151,6148],{},[16,7153,6769],{},[16,7155,6151],{},[16,7157,7158],{},[72,7159,6156],{},[20,7161,7162,7168],{},[23,7163,7164],{},[26,7165,31],{"href":7166,"rel":7167},"https://www.reddit.com/r/programming/comments/1ptyr3a/iceoryx2_v08_released/",[30],[23,7169,7170],{},[26,7171,2622],{"href":7172,"rel":7173},"https://programming.dev/post/42846946",[30],{"title":183,"searchDepth":217,"depth":217,"links":7175},[7176,7177,7185,7189,7190],{"id":2219,"depth":217,"text":2220},{"id":6900,"depth":217,"text":6901,"children":7178},[7179,7180,7182,7183,7184],{"id":6966,"depth":229,"text":6927},{"id":6987,"depth":229,"text":7181},"no_std and Bare-Metal Support",{"id":7011,"depth":229,"text":6941},{"id":7043,"depth":229,"text":6947},{"id":6029,"depth":229,"text":5153},{"id":7077,"depth":217,"text":7078,"children":7186},[7187,7188],{"id":7106,"depth":229,"text":7107},{"id":7125,"depth":229,"text":7126},{"id":6098,"depth":217,"text":6099},{"id":6144,"depth":217,"text":6145},"2025-12-23T00:00:00.000Z","Announcing the release of iceoryx2 version 0.8.0",{},"/blog/iceoryx2-0.8-release",{"title":6825,"description":7192},"blog/iceoryx2-0.8-release",[1295,3224,384,3606,3607,6821,7198],"csharp","rJ60G-qfUdIVvP4Zugv-pq6udOndd4XY2xd6IwmSU9M",{"id":7201,"title":7202,"author":7,"body":7203,"date":7929,"description":7930,"extension":1287,"featured":1288,"image":1289,"meta":7931,"navigation":239,"path":7932,"seo":7933,"stem":7934,"tags":7935,"__hash__":7938},"blog/blog/want-to-unlock-performance-and-clarity-use-strong-types.md","Want to Unlock Performance and Clarity? Use Strong Types!",{"type":9,"value":7204,"toc":7924},[7205,7208,7211,7225,7228,7274,7277,7320,7342,7346,7353,7356,7384,7387,7406,7604,7612,7616,7636,7871,7877,7884,7899,7902,7908,7911,7913,7921],[12,7206,7202],{"id":7207},"want-to-unlock-performance-and-clarity-use-strong-types",[16,7209,7210],{},"Christian Eltzschig - 01/06/2024",[20,7212,7213,7219],{},[23,7214,7215],{},[26,7216,31],{"href":7217,"rel":7218},"https://www.reddit.com/r/programming/comments/1d5pbxh/want_to_unlock_performance_and_clarity_use_strong/",[30],[23,7220,7221],{},[26,7222,38],{"href":7223,"rel":7224},"https://news.ycombinator.com/item?id=40546486",[30],[16,7226,7227],{},"C++ and Rust are strongly typed languages, meaning whenever you declare a\nvariable, you must either explicitly specify the variable",[5232,7229,7230,7255],{"tabs":5234},[5236,7231,7232],{"v-slot:rust":183},[178,7233,7235],{"className":382,"code":7234,"language":384,"meta":183,"style":183},"let fuu: i32 = 123;\n",[150,7236,7237],{"__ignoreMap":183},[187,7238,7239,7241,7244,7246,7248,7250,7253],{"class":189,"line":190},[187,7240,438],{"class":391},[187,7242,7243],{"class":410}," fuu",[187,7245,398],{"class":391},[187,7247,5292],{"class":193},[187,7249,404],{"class":391},[187,7251,7252],{"class":201}," 123",[187,7254,411],{"class":410},[5236,7256,7257],{"v-slot:cpp":183},[178,7258,7260],{"className":5329,"code":7259,"language":3606,"meta":183,"style":183},"int32_t fuu{123};\n",[150,7261,7262],{"__ignoreMap":183},[187,7263,7264,7267,7270,7272],{"class":189,"line":190},[187,7265,7266],{"class":391},"int32_t",[187,7268,7269],{"class":410}," fuu{",[187,7271,547],{"class":201},[187,7273,2832],{"class":410},[16,7275,7276],{},"or you do it implicitly by assigning a value of a specific type.",[5232,7278,7279,7300],{"tabs":5234},[5236,7280,7281],{"v-slot:rust":183},[178,7282,7284],{"className":382,"code":7283,"language":384,"meta":183,"style":183},"let fuu = \"hello world\";\n",[150,7285,7286],{"__ignoreMap":183},[187,7287,7288,7290,7293,7295,7298],{"class":189,"line":190},[187,7289,438],{"class":391},[187,7291,7292],{"class":410}," fuu ",[187,7294,444],{"class":391},[187,7296,7297],{"class":197}," \"hello world\"",[187,7299,411],{"class":410},[5236,7301,7302],{"v-slot:cpp":183},[178,7303,7305],{"className":5329,"code":7304,"language":3606,"meta":183,"style":183},"auto fuu = \"hello world\";\n",[150,7306,7307],{"__ignoreMap":183},[187,7308,7309,7312,7314,7316,7318],{"class":189,"line":190},[187,7310,7311],{"class":391},"auto",[187,7313,7292],{"class":410},[187,7315,444],{"class":391},[187,7317,7297],{"class":197},[187,7319,411],{"class":410},[16,7321,7322,7323,7326,7327,7330,7331,7334,7335,7338,7339,467],{},"The type of the variable also comes with a specific contract. An integer can\nonly contain numbers but not floating point values like ",[150,7324,7325],{},"3.14"," or a string. The\nsize of the integer also defines the range of numbers it can store.\nAn ",[150,7328,7329],{},"int8"," can store numbers in the range of ",[150,7332,7333],{},"[-128; 127]",", and\nan ",[150,7336,7337],{},"int16"," offers the range of ",[150,7340,7341],{},"[-32768, 32767]",[113,7343,7345],{"id":7344},"strong-types-implementation","Strong Types Implementation",[16,7347,7348,7349,7352],{},"With strong types, we have a powerful tool in our hands.\nWhen defining a function input argument as ",[150,7350,7351],{},"uint32_t",", we never\nneed to verify that the user accidentally gave us a negative number or a string. We never\nneed to test this case. All subsequent calls can rely on the fact that this is\nindeed an integer, and the API of the function clearly communicates that it is\nexpecting an integer and nothing else.",[16,7354,7355],{},"But we can also add semantic contracts to the type. Let's take a POSIX user name\nfor example.\nThe POSIX standard states that it is allowed to consist of:",[20,7357,7358,7365,7371],{},[23,7359,7360,7361,7364],{},"lower and upper ASCII letters (",[150,7362,7363],{},"a-zA-Z","),",[23,7366,7367,7368,671],{},"digits (",[150,7369,7370],{},"0-9",[23,7372,7373,7374,7376,7377,7380,7381,671],{},"and period (",[150,7375,467],{},"), underscore (",[150,7378,7379],{},"_",") and hyphen (",[150,7382,7383],{},"-",[16,7385,7386],{},"Furthermore, it is not allowed to start with a hyphen.",[16,7388,7389,7390,7393,7394,7396,7397,7399,7400,7402,7403,7405],{},"All of those constraints can be baked into a type called ",[150,7391,7392],{},"UserName",". The basic\nidea is that the ",[150,7395,7392],{}," cannot be created directly with a constructor.\nHowever, it comes with a static factory method called ",[150,7398,595],{}," - the Rust\nidiomatic approach is to call such a method ",[150,7401,542],{}," - which takes a string-literal\nas input argument and checks whether it meets the above requirements.\nThis method returns an optional value that contains either a\nvalid ",[150,7404,7392],{}," object or nothing when the user name contract is violated.",[5232,7407,7408,7511],{"tabs":5234},[5236,7409,7410],{"v-slot:rust":183},[178,7411,7413],{"className":382,"code":7412,"language":384,"meta":183,"style":183},"struct UserName {\n   value: String,\n};\n\nimpl UserName {\n   pub fn new(value: &str)\n                -> Option\u003CUserName>\n   {\n       //...\n   }\n}\n",[150,7414,7415,7424,7436,7440,7444,7453,7477,7492,7497,7502,7507],{"__ignoreMap":183},[187,7416,7417,7419,7422],{"class":189,"line":190},[187,7418,5337],{"class":391},[187,7420,7421],{"class":193}," UserName",[187,7423,1218],{"class":410},[187,7425,7426,7429,7431,7434],{"class":189,"line":217},[187,7427,7428],{"class":410},"   value",[187,7430,398],{"class":391},[187,7432,7433],{"class":193}," String",[187,7435,2827],{"class":410},[187,7437,7438],{"class":189,"line":229},[187,7439,2832],{"class":410},[187,7441,7442],{"class":189,"line":236},[187,7443,240],{"emptyLinePlaceholder":239},[187,7445,7446,7449,7451],{"class":189,"line":243},[187,7447,7448],{"class":391},"impl",[187,7450,7421],{"class":193},[187,7452,1218],{"class":410},[187,7454,7455,7458,7461,7464,7467,7469,7472,7475],{"class":189,"line":260},[187,7456,7457],{"class":391},"   pub",[187,7459,7460],{"class":391}," fn",[187,7462,7463],{"class":193}," new",[187,7465,7466],{"class":410},"(value",[187,7468,398],{"class":391},[187,7470,7471],{"class":391}," &",[187,7473,7474],{"class":193},"str",[187,7476,479],{"class":410},[187,7478,7479,7482,7485,7487,7489],{"class":189,"line":270},[187,7480,7481],{"class":391},"                ->",[187,7483,7484],{"class":193}," Option",[187,7486,501],{"class":410},[187,7488,7392],{"class":193},[187,7490,7491],{"class":410},">\n",[187,7493,7494],{"class":189,"line":276},[187,7495,7496],{"class":410},"   {\n",[187,7498,7499],{"class":189,"line":281},[187,7500,7501],{"class":232},"       //...\n",[187,7503,7504],{"class":189,"line":298},[187,7505,7506],{"class":410},"   }\n",[187,7508,7509],{"class":189,"line":308},[187,7510,1246],{"class":410},[5236,7512,7513],{"v-slot:cpp":183},[178,7514,7516],{"className":5329,"code":7515,"language":3606,"meta":183,"style":183},"class UserName {\n  private:\n    std::string value;\n\n  public:\n    static create(const std::string & value)\n                -> std::optional\u003CUserName>\n    {\n        // ...\n    }\n}\n",[150,7517,7518,7527,7532,7540,7544,7549,7571,7586,7591,7596,7600],{"__ignoreMap":183},[187,7519,7520,7523,7525],{"class":189,"line":190},[187,7521,7522],{"class":391},"class",[187,7524,7421],{"class":193},[187,7526,1218],{"class":410},[187,7528,7529],{"class":189,"line":217},[187,7530,7531],{"class":391},"  private:\n",[187,7533,7534,7537],{"class":189,"line":229},[187,7535,7536],{"class":193},"    std",[187,7538,7539],{"class":410},"::string value;\n",[187,7541,7542],{"class":189,"line":236},[187,7543,240],{"emptyLinePlaceholder":239},[187,7545,7546],{"class":189,"line":243},[187,7547,7548],{"class":391},"  public:\n",[187,7550,7551,7553,7556,7558,7560,7563,7566,7568],{"class":189,"line":260},[187,7552,5498],{"class":391},[187,7554,7555],{"class":193}," create",[187,7557,458],{"class":410},[187,7559,392],{"class":391},[187,7561,7562],{"class":193}," std",[187,7564,7565],{"class":410},"::string ",[187,7567,461],{"class":391},[187,7569,7570],{"class":410}," value)\n",[187,7572,7573,7575,7577,7580,7582,7584],{"class":189,"line":270},[187,7574,7481],{"class":391},[187,7576,7562],{"class":193},[187,7578,7579],{"class":410},"::optional",[187,7581,501],{"class":391},[187,7583,7392],{"class":410},[187,7585,7491],{"class":391},[187,7587,7588],{"class":189,"line":276},[187,7589,7590],{"class":410},"    {\n",[187,7592,7593],{"class":189,"line":281},[187,7594,7595],{"class":232},"        // ...\n",[187,7597,7598],{"class":189,"line":298},[187,7599,1240],{"class":410},[187,7601,7602],{"class":189,"line":308},[187,7603,1246],{"class":410},[16,7605,78,7606,7608,7609,7611],{},[150,7607,7392],{}," type now guarantees that it always contains a semantically\ncorrect user name since creating a ",[150,7610,7392],{}," with invalid characters is\nimpossible.",[113,7613,7615],{"id":7614},"fewer-bugs-more-expressive-apis","Fewer Bugs, More Expressive APIs",[16,7617,7618,7619,2827,7621,2782,7624,7627,7628,7631,7632,7635],{},"Let's assume we now have a collection of strong types like ",[150,7620,7392],{},[150,7622,7623],{},"GroupName",[150,7625,7626],{},"FileName",",  and we can use them directly in our API. We\nintroduce two functions. The first function ",[150,7629,7630],{},"do_stuff"," uses the new and shiny\nstrong types, but the second one ",[150,7633,7634],{},"buggy_stuff"," uses the underlying string of\nthose types directly.",[5232,7637,7638,7749],{"tabs":5234},[5236,7639,7640],{"v-slot:rust":183},[178,7641,7643],{"className":382,"code":7642,"language":384,"meta":183,"style":183},"fn do_stuff(\n    reader: &UserName,\n    writer: &GroupName,\n    storage: &FileName\n)\n\nfn buggy_stuff(\n    reader: &String,\n    writer: &String,\n    storage: &String\n)\n",[150,7644,7645,7655,7668,7681,7693,7697,7701,7710,7722,7734,7745],{"__ignoreMap":183},[187,7646,7647,7650,7653],{"class":189,"line":190},[187,7648,7649],{"class":391},"fn",[187,7651,7652],{"class":193}," do_stuff",[187,7654,1760],{"class":410},[187,7656,7657,7660,7662,7664,7666],{"class":189,"line":217},[187,7658,7659],{"class":410},"    reader",[187,7661,398],{"class":391},[187,7663,7471],{"class":391},[187,7665,7392],{"class":193},[187,7667,2827],{"class":410},[187,7669,7670,7673,7675,7677,7679],{"class":189,"line":229},[187,7671,7672],{"class":410},"    writer",[187,7674,398],{"class":391},[187,7676,7471],{"class":391},[187,7678,7623],{"class":193},[187,7680,2827],{"class":410},[187,7682,7683,7686,7688,7690],{"class":189,"line":236},[187,7684,7685],{"class":410},"    storage",[187,7687,398],{"class":391},[187,7689,7471],{"class":391},[187,7691,7692],{"class":193},"FileName\n",[187,7694,7695],{"class":189,"line":243},[187,7696,479],{"class":410},[187,7698,7699],{"class":189,"line":260},[187,7700,240],{"emptyLinePlaceholder":239},[187,7702,7703,7705,7708],{"class":189,"line":270},[187,7704,7649],{"class":391},[187,7706,7707],{"class":193}," buggy_stuff",[187,7709,1760],{"class":410},[187,7711,7712,7714,7716,7718,7720],{"class":189,"line":276},[187,7713,7659],{"class":410},[187,7715,398],{"class":391},[187,7717,7471],{"class":391},[187,7719,5989],{"class":193},[187,7721,2827],{"class":410},[187,7723,7724,7726,7728,7730,7732],{"class":189,"line":281},[187,7725,7672],{"class":410},[187,7727,398],{"class":391},[187,7729,7471],{"class":391},[187,7731,5989],{"class":193},[187,7733,2827],{"class":410},[187,7735,7736,7738,7740,7742],{"class":189,"line":298},[187,7737,7685],{"class":410},[187,7739,398],{"class":391},[187,7741,7471],{"class":391},[187,7743,7744],{"class":193},"String\n",[187,7746,7747],{"class":189,"line":308},[187,7748,479],{"class":410},[5236,7750,7751],{"v-slot:cpp":183},[178,7752,7754],{"className":5329,"code":7753,"language":3606,"meta":183,"style":183},"void do_stuff(\n    const UserName& reader,\n    const GroupName& writer,\n    const FileName& storage\n)\n\nvoid buggy_stuff(\n    const std::string& reader,\n    const std::string& writer,\n    const std::string& storage\n)\n",[150,7755,7756,7765,7779,7792,7804,7808,7812,7820,7837,7853,7867],{"__ignoreMap":183},[187,7757,7758,7761,7763],{"class":189,"line":190},[187,7759,7760],{"class":391},"void",[187,7762,7652],{"class":193},[187,7764,1760],{"class":410},[187,7766,7767,7770,7772,7774,7777],{"class":189,"line":217},[187,7768,7769],{"class":391},"    const",[187,7771,7421],{"class":193},[187,7773,461],{"class":391},[187,7775,747],{"class":7776},"s4XuR",[187,7778,2827],{"class":410},[187,7780,7781,7783,7786,7788,7790],{"class":189,"line":229},[187,7782,7769],{"class":391},[187,7784,7785],{"class":193}," GroupName",[187,7787,461],{"class":391},[187,7789,653],{"class":7776},[187,7791,2827],{"class":410},[187,7793,7794,7796,7799,7801],{"class":189,"line":236},[187,7795,7769],{"class":391},[187,7797,7798],{"class":193}," FileName",[187,7800,461],{"class":391},[187,7802,7803],{"class":7776}," storage\n",[187,7805,7806],{"class":189,"line":243},[187,7807,479],{"class":410},[187,7809,7810],{"class":189,"line":260},[187,7811,240],{"emptyLinePlaceholder":239},[187,7813,7814,7816,7818],{"class":189,"line":270},[187,7815,7760],{"class":391},[187,7817,7707],{"class":193},[187,7819,1760],{"class":410},[187,7821,7822,7824,7826,7828,7831,7833,7835],{"class":189,"line":276},[187,7823,7769],{"class":391},[187,7825,7562],{"class":193},[187,7827,498],{"class":410},[187,7829,7830],{"class":193},"string",[187,7832,461],{"class":391},[187,7834,747],{"class":7776},[187,7836,2827],{"class":410},[187,7838,7839,7841,7843,7845,7847,7849,7851],{"class":189,"line":281},[187,7840,7769],{"class":391},[187,7842,7562],{"class":193},[187,7844,498],{"class":410},[187,7846,7830],{"class":193},[187,7848,461],{"class":391},[187,7850,653],{"class":7776},[187,7852,2827],{"class":410},[187,7854,7855,7857,7859,7861,7863,7865],{"class":189,"line":298},[187,7856,7769],{"class":391},[187,7858,7562],{"class":193},[187,7860,498],{"class":410},[187,7862,7830],{"class":193},[187,7864,461],{"class":391},[187,7866,7803],{"class":7776},[187,7868,7869],{"class":189,"line":308},[187,7870,479],{"class":410},[16,7872,7873,7874,7876],{},"The first issue of the ",[150,7875,7634],{}," function is that the API is not expressive.\nShould the reader be a group name, a user name, or maybe it is even something completely different? This\nrequires some detailed documentation for the user. And if you know the saying,\n\"The compiler doesn't read comments and neither do I.\", you understand this is not a perfect solution.",[16,7878,7879,7880,7883],{},"Furthermore, it can be easily misused. When either variable names are not expressive enough or the function is\ncalled directly with values, they can be easily mixed up. Also, what happens when you refactor and swap or\nreplace some arguments? Maybe the ",[150,7881,7882],{},"storage"," shall be no longer a file name but now a database name. How do\nyou ensure that all function usages are ported?",[16,7885,7886,7887,7889,7890,535,7893,2782,7896,7898],{},"Additionally, the implementer of ",[150,7888,7634],{}," is now responsible for verifying all arguments! Whenever\nthis function is called, we must check that the ",[150,7891,7892],{},"reader",[150,7894,7895],{},"writer",[150,7897,7882],{}," are semantically correct.\nWhen this is not the case, we must handle it and inform the user.\nOf course, we could move this check into a free function and use it whenever we expect a type with a semantic\ncontract. However, this can be easily forgotten due to refactoring.",[16,7900,7901],{},"The error handling introduces further overhead! We have to write additional tests\nto check if the error handling works correctly and the function's users require\nextra logic to handle potential errors. And this extra logic needs to be tested as well!",[16,7903,7904,7905,7907],{},"Finally, it will cost us performance. Why? Because whenever one has a call chain where those arguments are\nforwarded to other functions, especially when they are not directly under your control, the same semantical\nverification has to be performed. Over and over again. And those function calls one uses to implement\n",[150,7906,7634],{}," may also fail for semantically incorrect values. This has to be handled and\ntested again. This costs even more performance!",[16,7909,7910],{},"All of those problems, performance costs, additional tests on the user and\nimplementer side, additional error handling, and an unexpressive API can be\navoided when we integrate the semantical check into the type itself so that\nwe have a guarantee that it always contains a valid value.",[113,7912,2590],{"id":2589},[16,7914,7915,7916,4926,7918,7920],{},"Using strong types like ",[150,7917,7392],{},[150,7919,7626],{}," comes with a bunch of benefits.\nFirstly, the API becomes more expressive and we no longer require extensive documentation to convey all the semantic details.\nStrong types can also prevent parameter mixups in functions with multiple arguments.\nFurthermore, they also minimize the lines of code by ensuring validity through the type system. With this, they decrease the need for error handling both within the implementation and for the user's code.\nEven the performance may improve when the semantic content is centrally verified and not in every function repeatedly.",[1271,7922,7923],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":183,"searchDepth":217,"depth":217,"links":7925},[7926,7927,7928],{"id":7344,"depth":229,"text":7345},{"id":7614,"depth":229,"text":7615},{"id":2589,"depth":229,"text":2590},"2024-06-01T00:00:00.000Z","Explore how using strong types in languages like C++ and Rust can enhance performance and code clarity by baking semantic contracts into the type system.",{},"/blog/want-to-unlock-performance-and-clarity-use-strong-types",{"title":7202,"description":7930},"blog/want-to-unlock-performance-and-clarity-use-strong-types",[3606,384,7936,7937],"clean-code","performance","58_Rr0wYNo5WY0N3ojhzcDUNx-W0zlVb07giLM9-Kdk",{"id":7940,"title":7941,"author":7,"body":7942,"date":8186,"description":8187,"extension":1287,"featured":239,"image":1289,"meta":8188,"navigation":239,"path":8189,"seo":8190,"stem":8191,"tags":8192,"__hash__":8194},"blog/blog/why-you-should-go-open-source.md","Why You Should Go Open-Source",{"type":9,"value":7943,"toc":8171},[7944,7947,7950,7953,7966,7973,7977,7988,7992,7996,7999,8002,8010,8014,8021,8028,8035,8039,8042,8045,8048,8051,8055,8058,8062,8066,8069,8072,8076,8083,8090,8093,8099,8108,8112,8115,8122,8125,8129,8141,8153,8160],[12,7945,7941],{"id":7946},"why-you-should-go-open-source",[16,7948,7949],{},"Christian Eltzschig - 09/04/2024",[16,7951,7952],{},"In this article, I would like to analyze ideas and misconceptions floating around\nwhen it comes to open-source software and provide arguments on why an\nopen-source strategy can be a success story.",[16,7954,7955,7956,7960,7961,467],{},"So, if you are a developer trying to convince your manager or you\nare the one who is currently exploring and deciding on the open-source\nstrategy, this article is for you. It is based on the experience we had\nwith our open-source project ",[26,7957,3265],{"href":7958,"rel":7959},"https://iceoryx.io",[30],",\nwhich led to the founding of our open-source company\n",[26,7962,7965],{"href":7963,"rel":7964},"https://ekxide.io",[30],"exkide",[16,7967,7968],{},[26,7969,7972],{"href":7970,"rel":7971},"https://www.reddit.com/r/opensource/comments/1bzqwz7/why_you_should_go_opensource/",[30],"Discuss the article on Reddit",[108,7974,7976],{"id":7975},"what-is-iceoryx","What Is iceoryx",[16,7978,7979,7982,7983,7987],{},[26,7980,3265],{"href":7958,"rel":7981},[30]," is a zero-copy inter-process\ncommunication framework written in\nC++/Rust. With ",[26,7984,7986],{"href":7963,"rel":7985},[30],"ekxide",", we founded a company\nthat backs up the\nopen-source project, provides commercial support and products around it, and\nsupports the community with new features, bug fixes, and tooling.",[108,7989,7991],{"id":7990},"lets-ask-the-business-team-to-open-source-our-software","Let's Ask The Business Team To Open-Source Our Software",[113,7993,7995],{"id":7994},"but-what-about-our-unique-selling-point","But What About Our Unique Selling Point?",[16,7997,7998],{},"One counterargument often used is, \"When we open-source our\nproduct, we give away one unique selling point!\".\nWhen you encounter this statement, it is worth digging deeper and understanding what unique\nthing the business people are trying to sell.",[16,8000,8001],{},"In our case, it is not zero-copy inter-process communication by itself.\nThis is necessary for most users in our domain, and there are already multiple custom\nclosed-source solutions.\nIf you would like to develop software for a car, a robot, or a medical\ndevice, you most likely require fast inter-process communication to deploy a\nrobust and efficient system.",[16,8003,8004,8005,467],{},"What makes our product unique is the upcoming support for zero-copy communication\non GPUs or across hypervisor partitions. So, a strategy could be to open-source\nthe core functionality, design and architecture that supports closed-source\nextensions, and promote them. This is not a new idea! It is the\n",[26,8006,8009],{"href":8007,"rel":8008},"https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle",[30],"Open-core model",[113,8011,8013],{"id":8012},"but-wouldnt-it-help-our-competitors","But Wouldn't It Help Our Competitors?",[16,8015,8016,8017,8020],{},"When a company open-sources software, other competitors can get inspired by it, use it, or fork and extend it. So they save time, create their product faster, and save money at the same time.\nBut this is only partially true. If you develop the product, you have the\nexpertise and the innovation on your side. Couple this with a well-defined\nOpen-Core business strategy, and you will be ahead.\nThe underlying issue may be something else.\nQuestion yourself, ",[72,8018,8019],{},"Do you rather want to succeed, or do you want your competitors to fail?","\nIf you want to succeed,\nwhat is the problem when your competitors also succeed?",[16,8022,8023,8024,8027],{},"If your software is well received and others start using it, you may\neven save money since there is a common interest in solving bugs and introducing new improvements\nand features. This may lead to cooperation between you and the community\nor they start contributing and you get new features for free.\nThis is how ",[26,8025,3265],{"href":7958,"rel":8026},[30]," got\nFreeRTOS platform support - thank you, NXP Semiconductors, for the contribution.",[16,8029,8030,8031,8034],{},"However, the most significant benefits are that you can define the ecosystem around your\nopen-source software, grow horizontally, and gain customers in domains you have\nnever thought of. When you invest time in the community, you also have access\nto a talent pool that may support you with bug fixes and features where you\nlack some expertise.\nBig thanks goes to our community for helping with the bazel support in\n",[26,8032,3265],{"href":7958,"rel":8033},[30]," where we still have some knowledge gaps.",[113,8036,8038],{"id":8037},"but-wouldnt-it-slow-down-development","But Wouldn't It Slow Down Development?",[16,8040,8041],{},"This argument comes more from the developer's side. The misconception is that\nthe maintenance overhead with additional testing, documentation, and a clean\ncode base is not worth the effort. It is required for the community to\nconsider your project, but it is also vital for yourself.\nThe proof-of-concept phase may be a bit slower, but as soon as this goes into\nproduction,\ndocumentation, clean code base, and test concept are not optional. Leaving out documentation, tests and code clean-ups\nwill produce faster results only in a brief period. After that, every additional feature will be more expensive and time-consuming just because\nof technical debt.",[16,8043,8044],{},"With poor tests, how are you sure the new features work and do not break\nexisting ones? With poor documentation, how can other developers (including your future self) use the software as intended and continue developing it further?",[16,8046,8047],{},"Isn't it something we all strive for as developers? Create something that is used\nalso in the future and continues evolving. To create something that matters\nand persists. If you are confident that your problem is a problem worth solving,\nothers may think the same. When the solution is closed-source, they will develop\ntheir custom solution, and your code may end up lost in some big mono-repo.",[16,8049,8050],{},"I believe the benefits you gain from open-sourcing outweigh the extra effort of additional documentation and community work. Not only does\nthe community benefit from it, but so do you too - when others will later\ncontinue the work and ideas you have started or stumble across all the\nedge cases you never thought of.",[113,8052,8054],{"id":8053},"but-how-to-sell-this-to-our-investors","But How To Sell This To Our Investors?",[16,8056,8057],{},"If you are working in a startup, your investors expect you to increase the value\nof your startup. How can this be achieved when providing software as\nopen-source? So the question is: why offer software as open source?\nLet's explore this in more detail.",[108,8059,8061],{"id":8060},"why-offer-software-as-open-source","Why Offer Software As Open Source",[113,8063,8065],{"id":8064},"set-the-standard","Set The Standard",[16,8067,8068],{},"Let's go back to the unique selling point. When your software is the only\nopen-source software that solves a particular problem, you can set the standard.\nWhen others provide proprietary solutions, they have to compete with you, and\nthey need to offer more advanced features worth the extra costs one\nhas to pay for their product - depending on your open-source license and\nbusiness model.\nFurthermore, with your solution, you can steer the ecosystem and define the\narchitecture and how your business will evolve around it.",[16,8070,8071],{},"When your project succeeds and reaches a critical mass, companies will require their supplier to be compatible with your solution to simplify their software stack. By offering an open-source solution, your\nproduct eliminates the need for a closed-source solution, and you have the\nadvantage of knowing your solution in great detail.",[113,8073,8075],{"id":8074},"horizontal-growth","Horizontal Growth",[16,8077,8078,8079,8082],{},"When your project flourishes, it will be used by users from different domains\nwith use cases you never thought of in the first place.\nWe were surprised when we noticed that fintech libraries, desktop applications, or computer-aided medical procedures are using ",[26,8080,3265],{"href":7958,"rel":8081},[30],", which was initially developed for the embedded safety-certified automotive market.",[16,8084,8085,8086,8089],{},"These new use cases also moved the frontier of what we strive for\nwith ",[26,8087,3265],{"href":7958,"rel":8088},[30],".\nSupport for new operating systems was requested, and they wanted to communicate via low-latency network protocols or become much more dynamic than the typical static safety-critical automotive use case. Now, we will work on language bindings for C#, Lua, Python, or Java, all things you usually do not encounter in a car but on a desktop machine.\nSo, after some time, we gained users we didn't even think of when we started the project.",[16,8091,8092],{},"When\nstarting a new project with a proof-of-concept phase, developers\nbegan to use our software. Since it is open source with a permissive\nlicense (Apache 2.0), they did not have to ask their manager for an\nevaluation license but could just use it.",[16,8094,8095,8096,467],{},"When their product matured enough, they required our advanced\nfeatures. But sometimes some pieces were missing, and who do you call when you have problems with the software you are\nusing - the company behind it! In this case ",[26,8097,7965],{"href":7963,"rel":8098},[30],[16,8100,8101,8102,8107],{},"Our core use case benefits from this as well. We also use those new tools and\nfeatures in our workday life. Windows is not running in cars, but it is nice to have the freedom\nto develop on any machine you want - from Windows, macOS, Linux to FreeBSD -\nthanks to the platform support community members like ",[26,8103,8106],{"href":8104,"rel":8105},"https://ecal.io",[30],"ecal"," requested.",[113,8109,8111],{"id":8110},"increase-your-talentpool","Increase Your Talentpool",[16,8113,8114],{},"Getting talented developers is a challenge many companies are facing,\nespecially when your particular field requires detailed domain\nknowledge.\nThe onboarding of new hires can be time-consuming,\nand the\nlack of experience in a specialized field may slow down the\ndevelopment process.",[16,8116,8117,8118,8121],{},"When building up a community that is welcoming and fun to interact with, you create a talent pool at your fingertips.\nYou observe who is shining with their contributions, and you have the advantage\nthat they do not need the entire onboarding process since they already know the product.\nWe also received applications just because people wanted to work with us on our\n",[26,8119,3265],{"href":7958,"rel":8120},[30]," project.",[16,8123,8124],{},"Even when employees leave the company, they stick around the project and\nare often supportive when you are in need. A good community has your back\nwhen it comes to an urgent bug fix or support in a feature where you lack the expertise.",[108,8126,8128],{"id":8127},"special-thanks","Special Thanks",[16,8130,8131,8132,8135,8136,467],{},"I want to conclude the article by saying thank you to the company that gave us\na cozy place to start our development of\n",[26,8133,3265],{"href":7958,"rel":8134},[30],"\nand supported us when we open-sourced our project,\n",[26,8137,8140],{"href":8138,"rel":8139},"https://www.bosch.de",[30],"Robert Bosch GmbH",[16,8142,8143,8144,8149,8150,467],{},"In the last 3 years, ",[26,8145,8148],{"href":8146,"rel":8147},"https://www.apex.ai",[30],"Apex.AI"," has been our home. The\natmosphere there did let us thrive and brought more features into\n",[26,8151,3265],{"href":7958,"rel":8152},[30],[16,8154,8155,8156,8159],{},"Without them, ",[26,8157,3265],{"href":7958,"rel":8158},[30]," wouldn't have been\nthe success story it is today.",[16,8161,8162,8163,8166,8167,8170],{},"The primary goal of our new company ",[26,8164,7986],{"href":7963,"rel":8165},[30]," is to focus now\nentirely on ",[26,8168,3265],{"href":7958,"rel":8169},[30],", boost\nfeature development further, and provide commercial support,\ntraining, and custom feature development for our community, users, and customers.",{"title":183,"searchDepth":217,"depth":217,"links":8172},[8173,8174,8180,8185],{"id":7975,"depth":217,"text":7976},{"id":7990,"depth":217,"text":7991,"children":8175},[8176,8177,8178,8179],{"id":7994,"depth":229,"text":7995},{"id":8012,"depth":229,"text":8013},{"id":8037,"depth":229,"text":8038},{"id":8053,"depth":229,"text":8054},{"id":8060,"depth":217,"text":8061,"children":8181},[8182,8183,8184],{"id":8064,"depth":229,"text":8065},{"id":8074,"depth":229,"text":8075},{"id":8110,"depth":229,"text":8111},{"id":8127,"depth":217,"text":8128},"2024-04-09T00:00:00.000Z","An analysis of open-source software strategies and their benefits, based on our experience with iceoryx.",{},"/blog/why-you-should-go-open-source",{"title":7941,"description":8187},"blog/why-you-should-go-open-source",[8193],"open-source","IGZQt7G30EEIuN8MzSX-bTE30mNv6hSZIuYLnVjS3-M",{"id":5042,"title":5043,"author":7,"body":8196,"date":6166,"description":6167,"extension":1287,"featured":1288,"image":1289,"meta":9086,"navigation":239,"path":6169,"seo":9087,"stem":6171,"tags":9088,"__hash__":6173},{"type":9,"value":8197,"toc":9080},[8198,8200,8202,8205,8207,8211,8213,8215,8220,8223,8250,8252,8257,8283,8285,8287,8289,8291,8293,8295,8297,8299,8301,8303,8305,8317,8322,8324,8326,8328,8332,8450,8452,8456,8458,8608,8613,8615,8617,8619,8621,8711,8713,8715,8719,8721,8733,8737,8745,8749,8751,8753,8765,8767,8819,8821,8835,8837,8849,8851,8875,8877,8891,8893,8895,8897,8907,8912,8924,8926,8928,8930,8932,8946,8948,8954,8966,8972,8984,8988,8990,8994,8999,9003,9017,9023,9037,9039,9044,9064,9068,9070,9072,9074,9078],[12,8199,5043],{"id":5048},[16,8201,5051],{},[2257,8203],{"src":3239,"alt":3240,"className":8204},[3242,2263],[113,8206,2220],{"id":2219},[16,8208,8209,3629],{},[72,8210,1295],{},[16,8212,5063],{},[16,8214,5066],{},[16,8216,3632,8217,3636],{},[26,8218,175],{"href":173,"rel":8219},[30],[2257,8221],{"src":3639,"alt":3377,"className":8222},[3379,2263],[20,8224,8225,8230,8235,8240,8245],{},[23,8226,8227],{},[26,8228,31],{"href":5081,"rel":8229},[30],[23,8231,8232],{},[26,8233,2622],{"href":5087,"rel":8234},[30],[23,8236,8237],{},[26,8238,47],{"href":45,"rel":8239},[30],[23,8241,8242],{},[26,8243,54],{"href":52,"rel":8244},[30],[23,8246,8247],{},[26,8248,61],{"href":59,"rel":8249},[30],[113,8251,5107],{"id":5106},[16,8253,5110,8254,467],{},[26,8255,5115],{"href":5113,"rel":8256},[30],[20,8258,8259,8263,8267,8271,8275,8279],{},[23,8260,8261],{},[26,8262,5123],{"href":5122},[23,8264,8265],{},[26,8266,5129],{"href":5128},[23,8268,8269],{},[26,8270,5135],{"href":5134},[23,8272,8273],{},[26,8274,5141],{"href":5140},[23,8276,8277],{},[26,8278,5147],{"href":5146},[23,8280,8281],{},[26,8282,5153],{"href":5152},[4448,8284,5123],{"id":5156},[5158,8286,5161],{"id":5160},[16,8288,5164],{},[5158,8290,5168],{"id":5167},[16,8292,5171],{},[16,8294,5174],{},[16,8296,5177],{},[5158,8298,5181],{"id":5180},[16,8300,5184],{},[5158,8302,111],{"id":110},[16,8304,5189],{},[20,8306,8307,8312],{},[23,8308,8309],{},[26,8310,5198],{"href":5196,"rel":8311},[30],[23,8313,8314],{},[26,8315,5205],{"href":5203,"rel":8316},[30],[16,8318,5208,8319,5214],{},[26,8320,5213],{"href":5211,"rel":8321},[30],[4448,8323,5129],{"id":5217},[16,8325,5220],{},[16,8327,5223],{},[16,8329,5226,8330,5230],{},[150,8331,5229],{},[5232,8333,8334,8414],{"tabs":5234},[5236,8335,8336],{"v-slot:rust":183},[178,8337,8338],{"className":382,"code":5240,"language":384,"meta":183,"style":183},[150,8339,8340,8356,8364,8374,8386,8398,8410],{"__ignoreMap":183},[187,8341,8342,8344,8346,8348,8350,8352,8354],{"class":189,"line":190},[187,8343,2841],{"class":410},[187,8345,2844],{"class":193},[187,8347,535],{"class":410},[187,8349,5253],{"class":193},[187,8351,535],{"class":410},[187,8353,5258],{"class":193},[187,8355,2852],{"class":410},[187,8357,8358,8360,8362],{"class":189,"line":217},[187,8359,2857],{"class":410},[187,8361,2860],{"class":193},[187,8363,2852],{"class":410},[187,8365,8366,8368,8370,8372],{"class":189,"line":229},[187,8367,2867],{"class":391},[187,8369,2870],{"class":391},[187,8371,5277],{"class":193},[187,8373,1218],{"class":410},[187,8375,8376,8378,8380,8382,8384],{"class":189,"line":236},[187,8377,5284],{"class":391},[187,8379,5287],{"class":410},[187,8381,398],{"class":391},[187,8383,5292],{"class":193},[187,8385,2827],{"class":410},[187,8387,8388,8390,8392,8394,8396],{"class":189,"line":243},[187,8389,5284],{"class":391},[187,8391,5301],{"class":410},[187,8393,398],{"class":391},[187,8395,5292],{"class":193},[187,8397,2827],{"class":410},[187,8399,8400,8402,8404,8406,8408],{"class":189,"line":260},[187,8401,5284],{"class":391},[187,8403,5314],{"class":410},[187,8405,398],{"class":391},[187,8407,401],{"class":193},[187,8409,2827],{"class":410},[187,8411,8412],{"class":189,"line":270},[187,8413,1246],{"class":410},[5236,8415,8416],{"v-slot:cpp":183},[178,8417,8418],{"className":5329,"code":5330,"language":3606,"meta":183,"style":183},[150,8419,8420,8428,8434,8440,8446],{"__ignoreMap":183},[187,8421,8422,8424,8426],{"class":189,"line":190},[187,8423,5337],{"class":391},[187,8425,5277],{"class":193},[187,8427,1218],{"class":410},[187,8429,8430,8432],{"class":189,"line":217},[187,8431,5346],{"class":391},[187,8433,5349],{"class":410},[187,8435,8436,8438],{"class":189,"line":229},[187,8437,5346],{"class":391},[187,8439,5356],{"class":410},[187,8441,8442,8444],{"class":189,"line":236},[187,8443,5361],{"class":391},[187,8445,5364],{"class":410},[187,8447,8448],{"class":189,"line":243},[187,8449,1246],{"class":410},[16,8451,5371],{},[16,8453,5374,8454,5378],{},[150,8455,5377],{},[16,8457,5381],{},[5232,8459,8460,8552],{"tabs":5234},[5236,8461,8462],{"v-slot:rust":183},[178,8463,8464],{"className":382,"code":5388,"language":384,"meta":183,"style":183},[150,8465,8466,8486,8494,8502,8512,8524,8536,8548],{"__ignoreMap":183},[187,8467,8468,8470,8472,8474,8476,8478,8480,8482,8484],{"class":189,"line":190},[187,8469,2841],{"class":410},[187,8471,2844],{"class":193},[187,8473,535],{"class":410},[187,8475,5253],{"class":193},[187,8477,535],{"class":410},[187,8479,5258],{"class":193},[187,8481,535],{"class":410},[187,8483,5409],{"class":193},[187,8485,2852],{"class":410},[187,8487,8488,8490,8492],{"class":189,"line":217},[187,8489,5416],{"class":410},[187,8491,5229],{"class":193},[187,8493,2852],{"class":410},[187,8495,8496,8498,8500],{"class":189,"line":229},[187,8497,2857],{"class":410},[187,8499,2860],{"class":193},[187,8501,2852],{"class":410},[187,8503,8504,8506,8508,8510],{"class":189,"line":236},[187,8505,2867],{"class":391},[187,8507,2870],{"class":391},[187,8509,5277],{"class":193},[187,8511,1218],{"class":410},[187,8513,8514,8516,8518,8520,8522],{"class":189,"line":243},[187,8515,5284],{"class":391},[187,8517,5287],{"class":410},[187,8519,398],{"class":391},[187,8521,5292],{"class":193},[187,8523,2827],{"class":410},[187,8525,8526,8528,8530,8532,8534],{"class":189,"line":260},[187,8527,5284],{"class":391},[187,8529,5301],{"class":410},[187,8531,398],{"class":391},[187,8533,5292],{"class":193},[187,8535,2827],{"class":410},[187,8537,8538,8540,8542,8544,8546],{"class":189,"line":270},[187,8539,5284],{"class":391},[187,8541,5314],{"class":410},[187,8543,398],{"class":391},[187,8545,401],{"class":193},[187,8547,2827],{"class":410},[187,8549,8550],{"class":189,"line":276},[187,8551,1246],{"class":410},[5236,8553,8554],{"v-slot:cpp":183},[178,8555,8556],{"className":5329,"code":5483,"language":3606,"meta":183,"style":183},[150,8557,8558,8566,8576,8586,8592,8598,8604],{"__ignoreMap":183},[187,8559,8560,8562,8564],{"class":189,"line":190},[187,8561,5337],{"class":391},[187,8563,5277],{"class":193},[187,8565,1218],{"class":410},[187,8567,8568,8570,8572,8574],{"class":189,"line":217},[187,8569,5498],{"class":391},[187,8571,5501],{"class":391},[187,8573,5504],{"class":391},[187,8575,5507],{"class":391},[187,8577,8578,8580,8582,8584],{"class":189,"line":229},[187,8579,5512],{"class":410},[187,8581,444],{"class":391},[187,8583,5517],{"class":197},[187,8585,411],{"class":410},[187,8587,8588,8590],{"class":189,"line":236},[187,8589,5346],{"class":391},[187,8591,5349],{"class":410},[187,8593,8594,8596],{"class":189,"line":243},[187,8595,5346],{"class":391},[187,8597,5356],{"class":410},[187,8599,8600,8602],{"class":189,"line":260},[187,8601,5361],{"class":391},[187,8603,5364],{"class":410},[187,8605,8606],{"class":189,"line":270},[187,8607,1246],{"class":410},[16,8609,3632,8610,5549],{},[26,8611,5548],{"href":5546,"rel":8612},[30],[5158,8614,5553],{"id":5552},[16,8616,5556],{},[16,8618,5559],{},[16,8620,5562],{},[178,8622,8623],{"className":382,"code":5565,"language":384,"meta":183,"style":183},[150,8624,8625,8645,8653,8661,8671,8683,8695,8707],{"__ignoreMap":183},[187,8626,8627,8629,8631,8633,8635,8637,8639,8641,8643],{"class":189,"line":190},[187,8628,2841],{"class":410},[187,8630,2844],{"class":193},[187,8632,535],{"class":410},[187,8634,5253],{"class":193},[187,8636,535],{"class":410},[187,8638,5258],{"class":193},[187,8640,535],{"class":410},[187,8642,5409],{"class":193},[187,8644,2852],{"class":410},[187,8646,8647,8649,8651],{"class":189,"line":217},[187,8648,5416],{"class":410},[187,8650,5229],{"class":193},[187,8652,2852],{"class":410},[187,8654,8655,8657,8659],{"class":189,"line":229},[187,8656,2857],{"class":410},[187,8658,2860],{"class":193},[187,8660,2852],{"class":410},[187,8662,8663,8665,8667,8669],{"class":189,"line":236},[187,8664,2867],{"class":391},[187,8666,2870],{"class":391},[187,8668,5277],{"class":193},[187,8670,1218],{"class":410},[187,8672,8673,8675,8677,8679,8681],{"class":189,"line":243},[187,8674,5284],{"class":391},[187,8676,5301],{"class":410},[187,8678,398],{"class":391},[187,8680,5292],{"class":193},[187,8682,2827],{"class":410},[187,8684,8685,8687,8689,8691,8693],{"class":189,"line":260},[187,8686,5284],{"class":391},[187,8688,5287],{"class":410},[187,8690,398],{"class":391},[187,8692,5292],{"class":193},[187,8694,2827],{"class":410},[187,8696,8697,8699,8701,8703,8705],{"class":189,"line":270},[187,8698,5284],{"class":391},[187,8700,5314],{"class":410},[187,8702,398],{"class":391},[187,8704,401],{"class":193},[187,8706,2827],{"class":410},[187,8708,8709],{"class":189,"line":276},[187,8710,1246],{"class":410},[16,8712,5656],{},[4448,8714,5135],{"id":5659},[16,8716,5662,8717,5666],{},[150,8718,5665],{},[16,8720,5669],{},[178,8722,8723],{"className":180,"code":5672,"language":182,"meta":183,"style":183},[150,8724,8725],{"__ignoreMap":183},[187,8726,8727,8729,8731],{"class":189,"line":190},[187,8728,194],{"class":193},[187,8730,5681],{"class":197},[187,8732,5684],{"class":197},[16,8734,5687,8735,5690],{},[150,8736,3464],{},[20,8738,8739,8741,8743],{},[23,8740,5695],{},[23,8742,5698],{},[23,8744,5701],{},[16,8746,5704,8747,5708],{},[150,8748,5707],{},[16,8750,5711],{},[16,8752,5714],{},[178,8754,8755],{"className":180,"code":5717,"language":182,"meta":183,"style":183},[150,8756,8757],{"__ignoreMap":183},[187,8758,8759,8761,8763],{"class":189,"line":190},[187,8760,3464],{"class":193},[187,8762,5726],{"class":197},[187,8764,5729],{"class":197},[16,8766,5732],{},[178,8768,8769],{"className":5735,"code":5736,"language":5737,"meta":183,"style":183},[150,8770,8771,8775,8779,8783,8787,8791,8795,8799,8803,8807,8811,8815],{"__ignoreMap":183},[187,8772,8773],{"class":189,"line":190},[187,8774,1760],{},[187,8776,8777],{"class":189,"line":217},[187,8778,5748],{},[187,8780,8781],{"class":189,"line":229},[187,8782,5753],{},[187,8784,8785],{"class":189,"line":236},[187,8786,5758],{},[187,8788,8789],{"class":189,"line":243},[187,8790,5763],{},[187,8792,8793],{"class":189,"line":260},[187,8794,5768],{},[187,8796,8797],{"class":189,"line":270},[187,8798,5773],{},[187,8800,8801],{"class":189,"line":276},[187,8802,5778],{},[187,8804,8805],{"class":189,"line":281},[187,8806,5783],{},[187,8808,8809],{"class":189,"line":298},[187,8810,5788],{},[187,8812,8813],{"class":189,"line":308},[187,8814,5793],{},[187,8816,8817],{"class":189,"line":314},[187,8818,479],{},[16,8820,5800],{},[178,8822,8823],{"className":180,"code":5803,"language":182,"meta":183,"style":183},[150,8824,8825],{"__ignoreMap":183},[187,8826,8827,8829,8831,8833],{"class":189,"line":190},[187,8828,3464],{"class":193},[187,8830,5726],{"class":197},[187,8832,5814],{"class":197},[187,8834,5817],{"class":197},[16,8836,5820],{},[178,8838,8839],{"className":180,"code":5823,"language":182,"meta":183,"style":183},[150,8840,8841],{"__ignoreMap":183},[187,8842,8843,8845,8847],{"class":189,"line":190},[187,8844,3464],{"class":193},[187,8846,1433],{"class":197},[187,8848,5729],{"class":197},[16,8850,5836],{},[178,8852,8853],{"className":5735,"code":5839,"language":5737,"meta":183,"style":183},[150,8854,8855,8859,8863,8867,8871],{"__ignoreMap":183},[187,8856,8857],{"class":189,"line":190},[187,8858,5846],{},[187,8860,8861],{"class":189,"line":217},[187,8862,5851],{},[187,8864,8865],{"class":189,"line":229},[187,8866,5856],{},[187,8868,8869],{"class":189,"line":236},[187,8870,5861],{},[187,8872,8873],{"class":189,"line":243},[187,8874,5866],{},[16,8876,5869],{},[178,8878,8879],{"className":180,"code":5872,"language":182,"meta":183,"style":183},[150,8880,8881],{"__ignoreMap":183},[187,8882,8883,8885,8887,8889],{"class":189,"line":190},[187,8884,3464],{"class":193},[187,8886,1433],{"class":197},[187,8888,5814],{"class":197},[187,8890,5885],{"class":197},[4448,8892,5889],{"id":5888},[16,8894,5892],{},[16,8896,5895],{},[20,8898,8899,8903],{},[23,8900,5900,8901,5904],{},[150,8902,5903],{},[23,8904,5907,8905,5911],{},[150,8906,5910],{},[16,8908,3679,8909,5919],{},[26,8910,5918],{"href":5916,"rel":8911},[30],[178,8913,8914],{"className":180,"code":5922,"language":182,"meta":183,"style":183},[150,8915,8916],{"__ignoreMap":183},[187,8917,8918,8920,8922],{"class":189,"line":190},[187,8919,3464],{"class":193},[187,8921,1433],{"class":197},[187,8923,5933],{"class":197},[16,8925,5936],{},[4448,8927,5409],{"id":5939},[16,8929,5942],{},[16,8931,5945],{},[20,8933,8934,8938,8942],{},[23,8935,8936,5953],{},[72,8937,5952],{},[23,8939,8940,5959],{},[72,8941,5958],{},[23,8943,8944],{},[72,8945,5964],{},[16,8947,5967],{},[16,8949,5970,8950,5974,8952,5977],{},[150,8951,5973],{},[150,8953,2860],{},[16,8955,5980,8956,5983,8958,5986,8960,4926,8962,5992,8964,5996],{},[150,8957,5409],{},[150,8959,5973],{},[150,8961,5989],{},[150,8963,2758],{},[150,8965,5995],{},[16,8967,5999,8968,4926,8970,6004],{},[150,8969,5989],{},[150,8971,2758],{},[20,8973,8974,8979],{},[23,8975,8976],{},[26,8977,6013],{"href":6011,"rel":8978},[30],[23,8980,8981,467],{},[26,8982,6020],{"href":6018,"rel":8983},[30],[16,8985,6023,8986,6026],{},[150,8987,5409],{},[4448,8989,5153],{"id":6029},[16,8991,8992,6035],{},[72,8993,6034],{},[16,8995,6038,8996,6043],{},[26,8997,6042],{"href":4444,"rel":8998},[30],[16,9000,9001,6049],{},[72,9002,6048],{},[2286,9004,9005,9009,9013],{},[23,9006,9007,6057],{},[150,9008,6056],{},[23,9010,9011],{},[150,9012,6062],{},[23,9014,9015],{},[150,9016,6067],{},[16,9018,9019,6073,9021,6077],{},[72,9020,6072],{},[150,9022,6076],{},[178,9024,9025],{"className":180,"code":6080,"language":182,"meta":183,"style":183},[150,9026,9027],{"__ignoreMap":183},[187,9028,9029,9031,9033,9035],{"class":189,"line":190},[187,9030,194],{"class":193},[187,9032,6089],{"class":197},[187,9034,6092],{"class":201},[187,9036,6095],{"class":197},[113,9038,6099],{"id":6098},[16,9040,6102,9041,6107],{},[26,9042,6106],{"href":3186,"rel":9043},[30],[20,9045,9046,9050,9054,9056,9058,9062],{},[23,9047,9048,6115],{},[150,9049,6114],{},[23,9051,6118,9052],{},[150,9053,6121],{},[23,9055,6124],{},[23,9057,6127],{},[23,9059,6130,9060],{},[72,9061,6133],{},[23,9063,6136],{},[16,9065,9066,6141],{},[150,9067,6121],{},[113,9069,6145],{"id":6144},[16,9071,6148],{},[16,9073,6151],{},[16,9075,9076],{},[72,9077,6156],{},[1271,9079,6159],{},{"title":183,"searchDepth":217,"depth":217,"links":9081},[9082,9083,9084,9085],{"id":2219,"depth":229,"text":2220},{"id":5106,"depth":229,"text":5107},{"id":6098,"depth":229,"text":6099},{"id":6144,"depth":229,"text":6145},{},{"title":5043,"description":6167},[1295,3224,384,3606,3607],1769159486883]