Last active
January 16, 2024 01:27
-
-
Save num8er/b70e77883151f3134647def4b6b57a30 to your computer and use it in GitHub Desktop.
client variable created in for loop is replacing previous one in previous thread
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "core:fmt" | |
import "core:net" | |
import "core:io" | |
import "core:thread" | |
import "core:time" | |
import "core:strings" | |
Client :: struct { | |
socket: net.TCP_Socket, | |
endpoint: net.Endpoint, | |
endpoint_as_string: string, | |
} | |
new_client :: proc(socket: net.TCP_Socket, endpoint: net.Endpoint) -> Client { | |
return Client{socket, endpoint, net.endpoint_to_string(endpoint)}; | |
} | |
main :: proc() { | |
endpoint, _ := net.parse_endpoint("127.0.0.1:8080"); | |
socket, err := net.listen_tcp(endpoint); | |
defer net.close(socket); | |
if err != nil { | |
fmt.println("Error listening on socket: ", err); | |
return; | |
} | |
fmt.println("Listening at ", net.endpoint_to_string(endpoint)); | |
for { | |
connection, endpoint, err := net.accept_tcp(socket); | |
if err != nil { | |
fmt.println("Error accepting connection: ", err); | |
return; | |
} | |
client := new_client(connection, endpoint); | |
fmt.println("Accepted connection from ", client.endpoint_as_string); | |
t := thread.create(proc(t: ^thread.Thread) { | |
client := cast (^Client) t.data; | |
handle_client(client); | |
}); | |
if t == nil { | |
fmt.eprintln("Error creating thread"); | |
net.close(client.socket); | |
continue; | |
} | |
t.user_index = len(threads); | |
t.data = &client; | |
append(&threads, t); | |
thread.start(t); | |
fmt.println("Started thread ", t.user_index); | |
fmt.println("Number of threads: ", len(threads)); | |
fmt.println(&client); | |
} | |
} | |
threads : [dynamic]^thread.Thread; | |
@(init) | |
create_thread_pool :: proc() { | |
threads := make([dynamic]^thread.Thread, 0); | |
thread_cleaner(); | |
} | |
destroy_thread_pool :: proc() { | |
delete(threads); | |
} | |
thread_cleaner :: proc() { | |
t := thread.create(proc(t : ^thread.Thread) { | |
for { | |
time.sleep(1 * time.Second); | |
if len(threads) == 0 { | |
continue; | |
} | |
for i := 0; i < len(threads); { | |
if t := threads[i]; thread.is_done(t) { | |
fmt.printf("Thread %d is done\n", t.user_index); | |
thread.destroy(t); | |
ordered_remove(&threads, i); | |
} | |
else { | |
i += 1; | |
} | |
} | |
} | |
}); | |
thread.start(t); | |
} | |
handle_client :: proc(client: ^Client) { | |
buffer_size :: 10240; | |
read_buffer : [buffer_size]byte = [buffer_size]byte{}; | |
bytes_read : int = 0; | |
err : net.Network_Error = nil; | |
for { | |
bytes_read, err = net.recv_tcp(client.socket, read_buffer[:]); | |
if err != nil { | |
fmt.println("Error reading from socket: ", err); | |
break; | |
} | |
if bytes_read == 0 { | |
break; | |
} | |
net.send_tcp(client.socket, []u8{'o', 'k', '\n'}); | |
fmt.println("Received message from ", client.endpoint_as_string, ":", string(read_buffer[:])); | |
} | |
fmt.println("Closing connection with ", client.endpoint_as_string); | |
net.close(client.socket); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "core:fmt" | |
import "core:net" | |
import "core:io" | |
import "core:thread" | |
import "core:time" | |
import "core:strings" | |
Client :: struct { | |
socket: net.TCP_Socket, | |
endpoint: net.Endpoint, | |
endpoint_as_string: string, | |
} | |
new_client :: proc(socket: net.TCP_Socket, endpoint: net.Endpoint) -> ^Client { | |
c := new(Client); | |
c.socket = socket; | |
c.endpoint = endpoint; | |
c.endpoint_as_string = net.endpoint_to_string(endpoint); | |
return c; | |
} | |
main :: proc() { | |
endpoint, _ := net.parse_endpoint("127.0.0.1:8080"); | |
socket, err := net.listen_tcp(endpoint); | |
defer net.close(socket); | |
if err != nil { | |
fmt.println("Error listening on socket: ", err); | |
return; | |
} | |
fmt.println("Listening at ", net.endpoint_to_string(endpoint)); | |
for { | |
connection, endpoint, err := net.accept_tcp(socket); | |
if err != nil { | |
fmt.println("Error accepting connection: ", err); | |
return; | |
} | |
client := new_client(connection, endpoint); | |
fmt.println("Accepted connection from ", client.endpoint_as_string); | |
t := thread.create(proc(t: ^thread.Thread) { | |
client := cast (^Client) t.data; | |
handle_client(client); | |
}); | |
if t == nil { | |
fmt.eprintln("Error creating thread"); | |
net.close(client.socket); | |
continue; | |
} | |
t.user_index = len(threads); | |
t.data = client; | |
append(&threads, t); | |
thread.start(t); | |
fmt.println("Started thread ", t.user_index); | |
fmt.println("Number of threads: ", len(threads)); | |
fmt.println(client); | |
} | |
} | |
threads : [dynamic]^thread.Thread; | |
@(init) | |
create_thread_pool :: proc() { | |
threads := make([dynamic]^thread.Thread, 0); | |
thread_cleaner(); | |
} | |
destroy_thread_pool :: proc() { | |
delete(threads); | |
} | |
thread_cleaner :: proc() { | |
t := thread.create(proc(t : ^thread.Thread) { | |
for { | |
time.sleep(1 * time.Second); | |
if len(threads) == 0 { | |
continue; | |
} | |
for i := 0; i < len(threads); { | |
if t := threads[i]; thread.is_done(t) { | |
fmt.printf("Thread %d is done\n", t.user_index); | |
thread.destroy(t); | |
ordered_remove(&threads, i); | |
} | |
else { | |
i += 1; | |
} | |
} | |
} | |
}); | |
thread.start(t); | |
} | |
handle_client :: proc(client: ^Client) { | |
buffer_size :: 10240; | |
read_buffer : [buffer_size]byte = [buffer_size]byte{}; | |
bytes_read : int = 0; | |
err : net.Network_Error = nil; | |
for { | |
bytes_read, err = net.recv_tcp(client.socket, read_buffer[:]); | |
if err != nil { | |
fmt.println("Error reading from socket: ", err); | |
break; | |
} | |
if bytes_read == 0 { | |
break; | |
} | |
net.send_tcp(client.socket, []u8{'o', 'k', '\n'}); | |
fmt.println("Received message from ", client.endpoint_as_string, ":", string(read_buffer[:])); | |
} | |
fmt.println("Closing connection with ", client.endpoint_as_string); | |
net.close(client.socket); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Explanation of solution:
in
main.odin
we were returning instance of struct as value and putting value to same stack variable client, so in next iteration we were rewriting same stack variable with new value.in
solution.odin
we create instance of struct and put it to heap and return pointer (^Client) which stack variable client is holding and passing it to thread. so next iteration simply replaces stack variable with new pointer which means previous instance is living in different memory address than new.