diff --git a/Cargo.lock b/Cargo.lock index 593220380..6d2575fae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2342,9 +2342,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" @@ -2972,7 +2972,7 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "zenoh" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-global-executor", "async-std", @@ -3007,6 +3007,7 @@ dependencies = [ "zenoh-config", "zenoh-core", "zenoh-crypto", + "zenoh-keyexpr", "zenoh-link", "zenoh-macros", "zenoh-plugin-trait", @@ -3021,7 +3022,7 @@ dependencies = [ [[package]] name = "zenoh-buffers" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "zenoh-collections", ] @@ -3051,7 +3052,7 @@ dependencies = [ [[package]] name = "zenoh-codec" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "log", "serde", @@ -3064,12 +3065,12 @@ dependencies = [ [[package]] name = "zenoh-collections" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" [[package]] name = "zenoh-config" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "flume", "json5", @@ -3088,7 +3089,7 @@ dependencies = [ [[package]] name = "zenoh-core" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "lazy_static", @@ -3098,7 +3099,7 @@ dependencies = [ [[package]] name = "zenoh-crypto" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "aes", "hmac", @@ -3111,7 +3112,7 @@ dependencies = [ [[package]] name = "zenoh-ext" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "bincode", @@ -3131,7 +3132,7 @@ dependencies = [ [[package]] name = "zenoh-keyexpr" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "hashbrown 0.14.0", "keyed-set", @@ -3145,7 +3146,7 @@ dependencies = [ [[package]] name = "zenoh-link" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "async-trait", @@ -3164,24 +3165,28 @@ dependencies = [ [[package]] name = "zenoh-link-commons" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "async-trait", "flume", + "log", "lz4_flex", "serde", "typenum", "zenoh-buffers", "zenoh-codec", + "zenoh-core", "zenoh-protocol", "zenoh-result", + "zenoh-sync", + "zenoh-util", ] [[package]] name = "zenoh-link-quic" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-rustls", "async-std", @@ -3207,7 +3212,7 @@ dependencies = [ [[package]] name = "zenoh-link-tcp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "async-trait", @@ -3223,7 +3228,7 @@ dependencies = [ [[package]] name = "zenoh-link-tls" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-rustls", "async-std", @@ -3248,7 +3253,7 @@ dependencies = [ [[package]] name = "zenoh-link-udp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "async-trait", @@ -3267,7 +3272,7 @@ dependencies = [ [[package]] name = "zenoh-link-unixsock_stream" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "async-trait", @@ -3285,7 +3290,7 @@ dependencies = [ [[package]] name = "zenoh-link-ws" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "async-trait", @@ -3305,7 +3310,7 @@ dependencies = [ [[package]] name = "zenoh-macros" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "proc-macro2", "quote", @@ -3318,7 +3323,7 @@ dependencies = [ [[package]] name = "zenoh-plugin-trait" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "const_format", "libloading", @@ -3334,7 +3339,7 @@ dependencies = [ [[package]] name = "zenoh-protocol" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "const_format", "hex", @@ -3350,7 +3355,7 @@ dependencies = [ [[package]] name = "zenoh-result" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "anyhow", ] @@ -3358,7 +3363,7 @@ dependencies = [ [[package]] name = "zenoh-shm" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "bincode", "log", @@ -3371,7 +3376,7 @@ dependencies = [ [[package]] name = "zenoh-sync" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "event-listener 4.0.0", @@ -3386,7 +3391,7 @@ dependencies = [ [[package]] name = "zenoh-transport" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-executor", "async-global-executor", @@ -3418,7 +3423,7 @@ dependencies = [ [[package]] name = "zenoh-util" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#2bd4518334d0a9e7e2703c7fd57dfa4547a96819" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" dependencies = [ "async-std", "async-trait", diff --git a/docs/examples.rst b/docs/examples.rst index 045187253..bea19cbbe 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -44,10 +44,10 @@ Subscribe #include "zenoh.h" void data_handler(const z_sample_t *sample, const void *arg) { - char *keystr = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); printf(">> Received (%s, %.*s)\n", keystr, (int)sample->payload.len, sample->payload.start); - free(keystr); + z_drop(z_move(keystr)); } int main(int argc, char **argv) { @@ -87,9 +87,9 @@ Query if (z_reply_is_ok(&reply)) { z_sample_t sample = z_reply_ok(&reply); - char *keystr = z_keyexpr_to_string(sample.keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); printf(">> Received ('%s': '%.*s')\n", keystr, (int)sample.payload.len, sample.payload.start); - free(keystr); + z_drop(z_move(keystr)); } } diff --git a/examples/z_ping.c b/examples/z_ping.c index ed5dff631..bb061baee 100644 --- a/examples/z_ping.c +++ b/examples/z_ping.c @@ -51,7 +51,7 @@ int main(int argc, char** argv) { z_owned_publisher_t pub = z_declare_publisher(z_loan(session), ping, NULL); z_owned_closure_sample_t respond = z_closure(callback, drop, (void*)(&pub)); z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), pong, z_move(respond), NULL); - uint8_t* data = malloc(args.size); + uint8_t* data = z_malloc(args.size); for (int i = 0; i < args.size; i++) { data[i] = i % 10; } @@ -75,7 +75,7 @@ int main(int argc, char** argv) { } } struct timespec t_start, t_stop, t_timeout; - unsigned long* results = malloc(sizeof(unsigned long) * args.number_of_pings); + unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (int i = 0; i < args.number_of_pings; i++) { clock_gettime(CLOCK_REALTIME, &t_timeout); t_timeout.tv_sec += PING_TIMEOUT_SEC; @@ -92,8 +92,8 @@ int main(int argc, char** argv) { printf("%d bytes: seq=%d rtt=%luµs, lat=%luµs\n", args.size, i, results[i], results[i] / 2); } z_mutex_unlock(&mutex); - free(results); - free(data); + z_free(results); + z_free(data); z_drop(z_move(sub)); z_drop(z_move(pub)); z_close(z_move(session)); diff --git a/examples/z_pub_thr.c b/examples/z_pub_thr.c index eb72432a0..8686c33eb 100644 --- a/examples/z_pub_thr.c +++ b/examples/z_pub_thr.c @@ -24,7 +24,7 @@ int main(int argc, char **argv) { char *keyexpr = "test/thr"; size_t len = atoi(argv[1]); - uint8_t *value = (uint8_t *)malloc(len); + uint8_t *value = (uint8_t *)z_malloc(len); memset(value, 1, len); z_owned_config_t config = z_config_default(); diff --git a/examples/z_scout.c b/examples/z_scout.c index ca5e8944b..3b882f547 100644 --- a/examples/z_scout.c +++ b/examples/z_scout.c @@ -83,14 +83,14 @@ void callback(z_owned_hello_t *hello, void *context) { void drop(void *context) { printf("Dropping scout\n"); int count = *(int *)context; - free(context); + z_free(context); if (!count) { printf("Did not find any zenoh process.\n"); } } int main(int argc, char **argv) { - int *context = malloc(sizeof(int)); + int *context = z_malloc(sizeof(int)); *context = 0; z_owned_scouting_config_t config = z_scouting_config_default(); z_owned_closure_hello_t closure = z_closure(callback, drop, context); diff --git a/examples/z_sub_thr.c b/examples/z_sub_thr.c index d82b6ea81..d32480174 100644 --- a/examples/z_sub_thr.c +++ b/examples/z_sub_thr.c @@ -26,7 +26,7 @@ typedef struct { } z_stats_t; z_stats_t *z_stats_make() { - z_stats_t *stats = malloc(sizeof(z_stats_t)); + z_stats_t *stats = z_malloc(sizeof(z_stats_t)); stats->count = 0; stats->finished_rounds = 0; stats->first_start.tv_nsec = 0; @@ -63,7 +63,7 @@ void drop_stats(void *context) { double elapsed_s = get_elapsed_s(&stats->first_start, &end); printf("Stats being dropped after unsubscribing: sent %ld messages over %f seconds (%f msg/s)\n", sent_messages, elapsed_s, (double)sent_messages / elapsed_s); - free(context); + z_free(context); } int main(int argc, char **argv) { diff --git a/include/zenoh.h b/include/zenoh.h index 94f90c2c4..444caf082 100644 --- a/include/zenoh.h +++ b/include/zenoh.h @@ -40,4 +40,5 @@ extern "C" { } #endif #include "zenoh_macros.h" +#include "zenoh_memory.h" #endif diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index bdefe4311..9bf02fe81 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -398,6 +398,13 @@ typedef struct z_timestamp_t { uint64_t time; struct z_id_t id; } z_timestamp_t; +/** + * QoS settings of zenoh message. + * + */ +typedef struct z_qos_t { + uint8_t _0; +} z_qos_t; /** * A data sample. * @@ -418,6 +425,7 @@ typedef struct z_sample_t { const void *_zc_buf; enum z_sample_kind_t kind; struct z_timestamp_t timestamp; + struct z_qos_t qos; struct z_attachment_t attachment; } z_sample_t; /** @@ -1744,6 +1752,22 @@ int8_t z_put(struct z_session_t session, * Constructs the default value for :c:type:`z_put_options_t`. */ ZENOHC_API struct z_put_options_t z_put_options_default(void); +/** + * Returns default qos settings. + */ +ZENOHC_API struct z_qos_t z_qos_default(void); +/** + * Returns message congestion control. + */ +ZENOHC_API enum z_congestion_control_t z_qos_get_congestion_control(struct z_qos_t qos); +/** + * Returns message express flag. If set to true, the message is not batched to reduce the latency. + */ +ZENOHC_API bool z_qos_get_express(struct z_qos_t qos); +/** + * Returns message priority. + */ +ZENOHC_API enum z_priority_t z_qos_get_priority(struct z_qos_t qos); /** * Returns the attachment to the query by aliasing. * diff --git a/include/zenoh_memory.h b/include/zenoh_memory.h new file mode 100644 index 000000000..0cf2a095a --- /dev/null +++ b/include/zenoh_memory.h @@ -0,0 +1,7 @@ +#pragma once +#include + +/*------------------ Memory ------------------*/ +static inline void *z_malloc(size_t size) { return malloc(size); } +static inline void *z_realloc(void *ptr, size_t size) {return realloc(ptr, size); } +static inline void z_free(void *ptr) {return free(ptr); } \ No newline at end of file diff --git a/src/commons.rs b/src/commons.rs index 5d58663eb..8ac21cb11 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -14,7 +14,10 @@ use crate::collections::*; use crate::keyexpr::*; +use crate::z_congestion_control_t; use crate::z_id_t; +use crate::z_priority_t; +use crate::{impl_guarded_transmute, GuardedTransmute}; use libc::c_void; use libc::{c_char, c_ulong}; use zenoh::buffers::ZBuf; @@ -22,6 +25,7 @@ use zenoh::prelude::SampleKind; use zenoh::prelude::SplitBuffer; use zenoh::query::ReplyKeyExpr; use zenoh::sample::Locality; +use zenoh::sample::QoS; use zenoh::sample::Sample; use zenoh_protocol::core::Timestamp; @@ -188,6 +192,47 @@ pub extern "C" fn zc_payload_null() -> zc_owned_payload_t { } } +/// QoS settings of zenoh message. +/// +#[repr(C)] +pub struct z_qos_t(u8); + +impl_guarded_transmute!(QoS, z_qos_t); +impl_guarded_transmute!(z_qos_t, QoS); + +impl From for z_qos_t { + fn from(qos: QoS) -> Self { + qos.transmute() + } +} + +impl From for QoS { + fn from(qos: z_qos_t) -> QoS { + qos.transmute() + } +} + +/// Returns message priority. +#[no_mangle] +pub extern "C" fn z_qos_get_priority(qos: z_qos_t) -> z_priority_t { + qos.transmute().priority().into() +} +/// Returns message congestion control. +#[no_mangle] +pub extern "C" fn z_qos_get_congestion_control(qos: z_qos_t) -> z_congestion_control_t { + qos.transmute().congestion_control().into() +} +/// Returns message express flag. If set to true, the message is not batched to reduce the latency. +#[no_mangle] +pub extern "C" fn z_qos_get_express(qos: z_qos_t) -> bool { + qos.transmute().express() +} +/// Returns default qos settings. +#[no_mangle] +pub extern "C" fn z_qos_default() -> z_qos_t { + QoS::default().transmute() +} + /// A data sample. /// /// A sample is the value associated to a given resource at a given point in time. @@ -207,6 +252,7 @@ pub struct z_sample_t<'a> { pub _zc_buf: &'a c_void, pub kind: z_sample_kind_t, pub timestamp: z_timestamp_t, + pub qos: z_qos_t, pub attachment: z_attachment_t, } @@ -222,6 +268,7 @@ impl<'a> z_sample_t<'a> { _zc_buf: unsafe { std::mem::transmute(owner) }, kind: sample.kind.into(), timestamp: sample.timestamp.as_ref().into(), + qos: sample.qos.into(), attachment: match &sample.attachment { Some(attachment) => z_attachment_t { data: attachment as *const _ as *mut c_void, diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index 98ac3bc94..ee63017c2 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -138,7 +138,7 @@ int main(int argc, char **argv) { sleep(SLEEP); size_t keyexpr_len = strlen(URI); - char *keyexpr_str = (char *)malloc(keyexpr_len + 1); + char *keyexpr_str = (char *)z_malloc(keyexpr_len + 1); memcpy(keyexpr_str, URI, keyexpr_len); keyexpr_str[keyexpr_len] = '\0'; int8_t _ret_int8 = z_keyexpr_is_canon(keyexpr_str, keyexpr_len); @@ -374,7 +374,7 @@ int main(int argc, char **argv) { sleep(SLEEP * 5); - free(keyexpr_str); + z_free(keyexpr_str); return 0; } diff --git a/tests/z_int_pub_sub_test.c b/tests/z_int_pub_sub_test.c index 8a2825618..cf005a80f 100644 --- a/tests/z_int_pub_sub_test.c +++ b/tests/z_int_pub_sub_test.c @@ -37,7 +37,10 @@ int run_publisher() { return -1; } - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); + z_publisher_options_t publisher_options = z_publisher_options_default(); + publisher_options.priority = Z_PRIORITY_DATA; + publisher_options.congestion_control = Z_CONGESTION_CONTROL_BLOCK; + z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), &publisher_options); if (!z_check(pub)) { perror("Unable to declare Publisher for key expression!"); return -1; @@ -68,6 +71,13 @@ void data_handler(const z_sample_t *sample, void *arg) { exit(-1); } + if (z_qos_get_congestion_control(sample->qos) != Z_CONGESTION_CONTROL_BLOCK + || z_qos_get_priority(sample->qos) != Z_PRIORITY_DATA + ) { + perror("Unexpected QoS values"); + exit(-1); + } + if (++val_num == values_count) { exit(0); };