Add Channel:peek()

This commit is contained in:
Bruce Hill 2024-08-18 23:31:36 -04:00
parent 1f16d63ac7
commit 9e07c6adc7
6 changed files with 47 additions and 1 deletions

View File

@ -91,6 +91,32 @@ get(channel:|T|) -> T
**Returns:**
The item removed from the channel.
**Example:**
```markdown
>> channel:peek()
= "Hello"
```
---
### `peek`
**Description:**
Returns the next item that will come out of the channel, but without removing
it. If the channel is empty, it waits until an item is available.
**Usage:**
```markdown
peek(channel:|T|) -> T
```
**Parameters:**
- `channel`: The channel from which to remove an item.
**Returns:**
The item removed from the channel.
**Example:**
```markdown
>> channel:get()

View File

@ -68,6 +68,16 @@ public void Channel$get(channel_t *channel, void *out, int64_t item_size, int64_
(void)pthread_cond_signal(&channel->cond);
}
public void Channel$peek(channel_t *channel, void *out, int64_t item_size)
{
(void)pthread_mutex_lock(&channel->mutex);
while (channel->items.length == 0)
pthread_cond_wait(&channel->cond, &channel->mutex);
memcpy(out, channel->items.data, item_size);
(void)pthread_mutex_unlock(&channel->mutex);
(void)pthread_cond_signal(&channel->cond);
}
public array_t Channel$view(channel_t *channel)
{
(void)pthread_mutex_lock(&channel->mutex);

View File

@ -15,6 +15,8 @@ void Channel$give(channel_t *channel, const void *item, int64_t padded_item_size
void Channel$give_all(channel_t *channel, array_t to_give, int64_t padded_item_size);
void Channel$get(channel_t *channel, void *out, int64_t item_size, int64_t padded_item_size);
#define Channel$get_value(channel, t, padded_item_size) ({ t _val; Channel$get(channel, &_val, sizeof(t), padded_item_size); _val; })
void Channel$peek(channel_t *channel, void *out, int64_t item_size);
#define Channel$peek_value(channel, t) ({ t _val; Channel$peek(channel, &_val, sizeof(t)); _val; })
void Channel$clear(channel_t *channel);
array_t Channel$view(channel_t *channel);
uint32_t Channel$hash(const channel_t **channel, const TypeInfo *type);

View File

@ -2377,6 +2377,10 @@ CORD compile(env_t *env, ast_t *ast)
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
(void)compile_arguments(env, ast, NULL, call->args);
return CORD_all("Channel$get_value(", self, ", ", compile_type(item_t), ", ", padded_item_size, ")");
} else if (streq(call->name, "peek")) {
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
(void)compile_arguments(env, ast, NULL, call->args);
return CORD_all("Channel$peek_value(", self, ", ", compile_type(item_t), ")");
} else if (streq(call->name, "clear")) {
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
(void)compile_arguments(env, ast, NULL, call->args);

View File

@ -2,6 +2,10 @@ enum Job(Increment(x:Int), Decrement(x:Int))
func main():
jobs := |:Job; max_size=2|
>> jobs:give(Increment(5))
>> jobs:peek()
= Job.Increment(x=5)
results := |:Int; max_size|
>> thread := Thread.new(func():
//! In another thread!
@ -13,7 +17,6 @@ func main():
>> results:give(x-1)
)
>> jobs:give(Increment(5))
>> jobs:give(Decrement(100))
>> jobs:give(Decrement(100))
>> jobs:give(Decrement(100))

View File

@ -774,6 +774,7 @@ type_t *get_type(env_t *env, ast_t *ast)
else if (streq(call->name, "get")) return Match(self_value_t, ChannelType)->item_type;
else if (streq(call->name, "give")) return Type(VoidType);
else if (streq(call->name, "give_all")) return Type(VoidType);
else if (streq(call->name, "peek")) return Match(self_value_t, ChannelType)->item_type;
else if (streq(call->name, "view")) return Type(ArrayType, .item_type=Match(self_value_t, ChannelType)->item_type);
else code_err(ast, "There is no '%s' method for arrays", call->name);
}