Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / fdhandle.c
1
2 #include "fdhandle.h"
3 #include "utils/mono-lazy-init.h"
4 #include "utils/mono-coop-mutex.h"
5
6 static GHashTable *fds;
7 static MonoCoopMutex fds_mutex;
8 static MonoFDHandleCallback fds_callback[MONO_FDTYPE_COUNT];
9 static mono_lazy_init_t fds_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
10
11 static const gchar *types_str[] = {
12         "File",
13         "Console",
14         "Pipe",
15         "Socket",
16         NULL
17 };
18
19 static void
20 fds_remove (gpointer data)
21 {
22         MonoFDHandle* fdhandle;
23
24         fdhandle = (MonoFDHandle*) data;
25         g_assert (fdhandle);
26
27         g_assert (fds_callback [fdhandle->type].close);
28         fds_callback [fdhandle->type].close (fdhandle);
29
30         mono_refcount_dec (fdhandle);
31 }
32
33 static void
34 initialize (void)
35 {
36         fds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, fds_remove);
37         mono_coop_mutex_init (&fds_mutex);
38 }
39
40 void
41 mono_fdhandle_register (MonoFDType type, MonoFDHandleCallback *callback)
42 {
43         mono_lazy_initialize (&fds_init, initialize);
44         memcpy (&fds_callback [type], callback, sizeof (MonoFDHandleCallback));
45 }
46
47 static void
48 fdhandle_destroy (gpointer data)
49 {
50         MonoFDHandle* fdhandle;
51
52         fdhandle = (MonoFDHandle*) data;
53         g_assert (fdhandle);
54
55         g_assert (fds_callback [fdhandle->type].destroy);
56         fds_callback [fdhandle->type].destroy (fdhandle);
57 }
58
59 void
60 mono_fdhandle_init (MonoFDHandle *fdhandle, MonoFDType type, gint fd)
61 {
62         mono_refcount_init (fdhandle, fdhandle_destroy);
63         fdhandle->type = type;
64         fdhandle->fd = fd;
65 }
66
67 void
68 mono_fdhandle_insert (MonoFDHandle *fdhandle)
69 {
70         mono_coop_mutex_lock (&fds_mutex);
71
72         if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL))
73                 g_error("%s: duplicate %s fd %d", __func__, types_str [fdhandle->type], fdhandle->fd);
74
75         g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
76
77         mono_coop_mutex_unlock (&fds_mutex);
78 }
79
80 gboolean
81 mono_fdhandle_try_insert (MonoFDHandle *fdhandle)
82 {
83         mono_coop_mutex_lock (&fds_mutex);
84
85         if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL)) {
86                 /* we raced between 2 invocations of mono_fdhandle_try_insert */
87                 mono_coop_mutex_unlock (&fds_mutex);
88
89                 return FALSE;
90         }
91
92         g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
93
94         mono_coop_mutex_unlock (&fds_mutex);
95
96         return TRUE;
97 }
98
99 gboolean
100 mono_fdhandle_lookup_and_ref (gint fd, MonoFDHandle **fdhandle)
101 {
102         mono_coop_mutex_lock (&fds_mutex);
103
104         if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) fdhandle)) {
105                 mono_coop_mutex_unlock (&fds_mutex);
106                 return FALSE;
107         }
108
109         mono_refcount_inc (*fdhandle);
110
111         mono_coop_mutex_unlock (&fds_mutex);
112
113         return TRUE;
114 }
115
116 void
117 mono_fdhandle_unref (MonoFDHandle *fdhandle)
118 {
119         mono_refcount_dec (fdhandle);
120 }
121
122 gboolean
123 mono_fdhandle_close (gint fd)
124 {
125         MonoFDHandle *fdhandle;
126         gboolean removed;
127
128         mono_coop_mutex_lock (&fds_mutex);
129
130         if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) &fdhandle)) {
131                 mono_coop_mutex_unlock (&fds_mutex);
132
133                 return FALSE;
134         }
135
136         removed = g_hash_table_remove (fds, GINT_TO_POINTER(fdhandle->fd));
137         g_assert (removed);
138
139         mono_coop_mutex_unlock (&fds_mutex);
140
141         return TRUE;
142 }