affq19

affq19

ChatRoom in Elixir using Mutex and Threads

Hi! I’ve been studying concurrency models with elixir. Now, I want to develop a ChatRoom, where users can Join, post messages, and disconnect themselves using threads and mutex in elixir. So far I have developed the model for entering new users and disconnect them. However, I have put some “prints” to see how its working, but they are not showing when I run the program. This is the code,

defmodule MyMutex do
  @mutex :free

  def lock(:free) do
    {:ok, :locked}
  end

  def lock(:locked) do
    {:error, :already_locked}
  end

  def unlock(:locked) do
    :ok
  end

  def unlock(:free) do
    {:error, :not_locked}
  end
end

defmodule Chat do

  defstruct users: [], messages: [], mutex: MyMutex

  def start_link() do
    {:ok, pid} = Task.start_link(fn -> action(%__MODULE__{}) end)
  end

  defp action(chat) do
    receive do
    {:join, :user} ->
      chat = new_user(chat, :user)
      action(chat)
    #{:post, user} ->
    #  chat = post_message(chat, user)
    #  action(chat)
    {:disconnect, user} ->
      chat = disconnect_user(chat, user)
      action(chat)
    {:users_chat} ->
      post_all_users(chat)
      action(chat)
    end
  end

  defp post_all_users(chat) do
    Enum.each(chat.users, fn user ->
      "User:"
    end)
  end

  defp post_message_to_all(chat, message) do
    Enum.each(chat.users, fn user ->
      IO.puts("Message from server: #{message} (Sent to: #{user})")
    end)
  end

  defp new_user(chat ,user) do
    {:ok, mutex} = MyMutex.lock(chat.mutex)
    updated_chat = %{ chat | users: chat.users ++ [user], mutex: mutex }
    IO.puts("Entering the chat: #{user}")
    MyMutex.unlock(mutex)
    post_message_to_all(updated_chat, "#{user} has joined the chat.")
    updated_chat
  end

  defp disconnect_user(chat, user) do
    {:ok, mutex} = MyMutex.lock(chat.mutex)
    chat = %{chat | users: List.delete(chat.users, user),
            mutex: mutex}
    IO.puts("The user #{user} has leaved the chat")
    MyMutex.lock(mutex)
    chat
  end

end

Thanks in Advice :slight_smile:

Most Liked

dimitarvp

dimitarvp

What was your education source that claimed you need mutexes in Elixir? :thinking:

You don’t need them here.

kokolegorille

kokolegorille

Hello and welcome,

Do You really need mutex in Elixir?

You might be interested by this YT video

by @geo

arijoon

arijoon

I have to agree with other posters regarding mutex. General usecase for a mutex is to lock a shared resource when multiple threads are writing to it. In erlang we have processes which do not share resources. If you wish to share something (for example the chat messages), you can create a new process which holds this information and read/write to it by sending messages to that process. Since the process will only action one message at a time, no mutex will be required

dimitarvp

dimitarvp

Do you know of GenServer?

voughtdq

voughtdq

@affq19 I made some revisions to your code to get it to work. There are commit messages that you can look at to understand why the changes were made. I’ve also added a simple test module to test it. It can be invoked from iex like this:

c("chat.ex")
Test.run()

As has been discussed, the mutex really isn’t necessary here and implementing this using either Process.spawn/1,3 or as a GenServer is the correct way to do it. You should be able to safely remove the mutex code without it affecting anything and it might be a good first step to make the code more Elixirish.

Where Next?

Popular in Questions Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New

Other popular topics Top

gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

We're in Beta

About us Mission Statement