comparison src/mex.cc @ 5905:e5c0831a48bd

[project @ 2006-07-26 19:27:48 by jwe]
author jwe
date Wed, 26 Jul 2006 19:27:48 +0000
parents 11bb9bf343a0
children 288c341438f9
comparison
equal deleted inserted replaced
5904:80d3933fb8b6 5905:e5c0831a48bd
26 #include "unwind-prot.h" 26 #include "unwind-prot.h"
27 #include "utils.h" 27 #include "utils.h"
28 #include "variables.h" 28 #include "variables.h"
29 29
30 // #define DEBUG 1 30 // #define DEBUG 1
31
32 static void
33 xfree (void *ptr)
34 {
35 #ifdef DEBUG
36 std::cerr << "free: " << ptr << std::endl;
37 #endif
38
39 ::free (ptr);
40 }
31 41
32 static int 42 static int
33 max_str_len (int m, const char **str) 43 max_str_len (int m, const char **str)
34 { 44 {
35 int max_len = 0; 45 int max_len = 0;
1516 mxFree (fields); 1526 mxFree (fields);
1517 1527
1518 int ntot = nfields * get_number_of_elements (); 1528 int ntot = nfields * get_number_of_elements ();
1519 1529
1520 for (int i = 0; i < ntot; i++) 1530 for (int i = 0; i < ntot; i++)
1521 mxDestroyArray (data[i]); 1531 delete data[i];
1522 1532
1523 mxFree (data); 1533 mxFree (data);
1524 } 1534 }
1525 1535
1526 octave_value as_octave_value (void) const 1536 octave_value as_octave_value (void) const
1736 ~mxArray_cell (void) 1746 ~mxArray_cell (void)
1737 { 1747 {
1738 int nel = get_number_of_elements (); 1748 int nel = get_number_of_elements ();
1739 1749
1740 for (int i = 0; i < nel; i++) 1750 for (int i = 0; i < nel; i++)
1741 mxDestroyArray (data[i]); 1751 delete data[i];
1742 1752
1743 mxFree (data); 1753 mxFree (data);
1744 } 1754 }
1745 1755
1746 octave_value as_octave_value (void) const 1756 octave_value as_octave_value (void) const
1885 mex (void) : memlist (), arraylist (), fname (0) { } 1895 mex (void) : memlist (), arraylist (), fname (0) { }
1886 1896
1887 ~mex (void) 1897 ~mex (void)
1888 { 1898 {
1889 if (! memlist.empty ()) 1899 if (! memlist.empty ())
1890 error ("mex: cleanup failed"); 1900 error ("mex: %s: cleanup failed", function_name ());
1891 1901
1892 mxFree (fname); 1902 mxFree (fname);
1893 } 1903 }
1894 1904
1895 const char *function_name (void) const 1905 const char *function_name (void) const
1913 // Free all unmarked pointers obtained from malloc and calloc. 1923 // Free all unmarked pointers obtained from malloc and calloc.
1914 static void cleanup (void *ptr) 1924 static void cleanup (void *ptr)
1915 { 1925 {
1916 mex *context = static_cast<mex *> (ptr); 1926 mex *context = static_cast<mex *> (ptr);
1917 1927
1928 // We can't use mex::free here because it modifies memlist.
1918 for (std::set<void *>::iterator p = context->memlist.begin (); 1929 for (std::set<void *>::iterator p = context->memlist.begin ();
1919 p != context->memlist.end (); p++) 1930 p != context->memlist.end (); p++)
1920 context->free (*p); 1931 {
1921 1932 if (*p)
1933 {
1934 context->unmark (*p);
1935
1936 xfree (*p);
1937 }
1938 }
1939
1940 context->memlist.clear ();
1941
1942 // We can't use mex::free_value here because it modifies arraylist.
1922 for (std::set<mxArray *>::iterator p = context->arraylist.begin (); 1943 for (std::set<mxArray *>::iterator p = context->arraylist.begin ();
1923 p != context->arraylist.end (); p++) 1944 p != context->arraylist.end (); p++)
1924 context->free_value (*p); 1945 delete *p;
1946
1947 context->arraylist.clear ();
1925 } 1948 }
1926 1949
1927 // allocate a pointer, and mark it to be freed on exit 1950 // allocate a pointer, and mark it to be freed on exit
1928 void *malloc_unmarked (size_t n) 1951 void *malloc_unmarked (size_t n)
1929 { 1952 {
1936 if (! ptr) 1959 if (! ptr)
1937 { 1960 {
1938 // FIXME -- could use "octave_new_handler();" instead 1961 // FIXME -- could use "octave_new_handler();" instead
1939 1962
1940 error ("%s: failed to allocate %d bytes of memory", 1963 error ("%s: failed to allocate %d bytes of memory",
1941 mexFunctionName (), n); 1964 function_name (), n);
1942 1965
1943 abort (); 1966 abort ();
1944 } 1967 }
1945 1968
1946 global_mark (ptr); 1969 global_mark (ptr);
2016 2039
2017 if (p != global_memlist.end ()) 2040 if (p != global_memlist.end ())
2018 { 2041 {
2019 global_memlist.erase (p); 2042 global_memlist.erase (p);
2020 2043
2021 #ifdef DEBUG 2044 xfree (ptr);
2022 std::cerr << "free: " << ptr << std::endl;
2023 #endif
2024 ::free (ptr);
2025 } 2045 }
2026 else 2046 else
2027 warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc"); 2047 warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc");
2028 } 2048 }
2029 } 2049 }
2041 } 2061 }
2042 2062
2043 // Free an array and its contents. 2063 // Free an array and its contents.
2044 void free_value (mxArray *ptr) 2064 void free_value (mxArray *ptr)
2045 { 2065 {
2046 arraylist.erase (ptr); 2066 std::set<mxArray *>::iterator p = arraylist.find (ptr);
2047 delete ptr; 2067
2068 if (p != arraylist.end ())
2069 {
2070 arraylist.erase (p);
2071 delete ptr;
2072 }
2073 #ifdef DEBUG
2074 else
2075 warning ("mex::free_value: skipping memory not allocated by mex::make_value");
2076 #endif
2048 } 2077 }
2049 2078
2050 // Mark an array and its contents so it will not be freed on exit. 2079 // Mark an array and its contents so it will not be freed on exit.
2051 void persistent (mxArray *ptr) 2080 void persistent (mxArray *ptr)
2052 { 2081 {
2075 // Mark a pointer to be freed on exit. 2104 // Mark a pointer to be freed on exit.
2076 void mark (void *p) 2105 void mark (void *p)
2077 { 2106 {
2078 #ifdef DEBUG 2107 #ifdef DEBUG
2079 if (memlist.find (p) != memlist.end ()) 2108 if (memlist.find (p) != memlist.end ())
2080 warning ("%s: double registration ignored", mexFunctionName ()); 2109 warning ("%s: double registration ignored", function_name ());
2081 #endif 2110 #endif
2082 2111
2083 memlist.insert (p); 2112 memlist.insert (p);
2084 } 2113 }
2085 2114
2086 // Unmark a pointer to be freed on exit, either because it was 2115 // Unmark a pointer to be freed on exit, either because it was
2087 // made persistent, or because it was already freed. 2116 // made persistent, or because it was already freed.
2088 void unmark (void *p) 2117 void unmark (void *ptr)
2089 { 2118 {
2119 std::set<void *>::iterator p = memlist.find (ptr);
2120
2121 if (p != memlist.end ())
2122 memlist.erase (p);
2090 #ifdef DEBUG 2123 #ifdef DEBUG
2091 if (memlist.find (p) != memlist.end ()) 2124 else
2092 warning ("%s: value not marked", mexFunctionName ()); 2125 warning ("%s: value not marked", function_name ());
2093 #endif 2126 #endif
2094
2095 memlist.erase (p);
2096 } 2127 }
2097 2128
2098 // List of memory resources we allocated. 2129 // List of memory resources we allocated.
2099 static std::set<void *> global_memlist; 2130 static std::set<void *> global_memlist;
2100 2131
2101 // Mark a pointer as one we allocated. 2132 // Mark a pointer as one we allocated.
2102 void global_mark (void *p) 2133 void global_mark (void *ptr)
2103 { 2134 {
2104 #ifdef DEBUG 2135 #ifdef DEBUG
2105 if (global_memlist.find (p) != global_memlist.end ()) 2136 if (global_memlist.find (ptr) != global_memlist.end ())
2106 warning ("%s: double registration ignored", mexFunctionName ()); 2137 warning ("%s: double registration ignored", function_name ());
2107 #endif 2138 #endif
2108 2139
2109 global_memlist.insert (p); 2140 global_memlist.insert (ptr);
2110 } 2141 }
2111 2142
2112 // Unmark a pointer as one we allocated. 2143 // Unmark a pointer as one we allocated.
2113 void global_unmark (void *p) 2144 void global_unmark (void *ptr)
2114 { 2145 {
2146 std::set<void *>::iterator p = global_memlist.find (ptr);
2147
2148 if (p != global_memlist.end ())
2149 global_memlist.erase (p);
2115 #ifdef DEBUG 2150 #ifdef DEBUG
2116 if (global_memlist.find (p) != global_memlist.end ()) 2151 else
2117 warning ("%s: value not marked", mexFunctionName ()); 2152 warning ("%s: value not marked", function_name ());
2118 #endif 2153 #endif
2119 2154
2120 global_memlist.erase (p);
2121 } 2155 }
2122 }; 2156 };
2123 2157
2124 // List of memory resources we allocated. 2158 // List of memory resources we allocated.
2125 std::set<void *> mex::global_memlist; 2159 std::set<void *> mex::global_memlist;
2771 int nout = nargout == 0 ? 1 : nargout; 2805 int nout = nargout == 0 ? 1 : nargout;
2772 OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout); 2806 OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout);
2773 for (int i = 0; i < nout; i++) 2807 for (int i = 0; i < nout; i++)
2774 argout[i] = 0; 2808 argout[i] = 0;
2775 2809
2810 unwind_protect::begin_frame ("call_mex");
2811
2812 // Save old mex pointer.
2813 unwind_protect_ptr (mex_context);
2814
2776 mex context; 2815 mex context;
2777 2816
2778 unwind_protect::add (mex::cleanup, static_cast<void *> (&context)); 2817 unwind_protect::add (mex::cleanup, static_cast<void *> (&context));
2779 2818
2780 for (int i = 0; i < nargin; i++) 2819 for (int i = 0; i < nargin; i++)
2781 argin[i] = context.make_value (args(i)); 2820 argin[i] = context.make_value (args(i));
2782
2783 // Save old mex pointer.
2784 unwind_protect_ptr (mex_context);
2785 2821
2786 if (setjmp (context.jump) == 0) 2822 if (setjmp (context.jump) == 0)
2787 { 2823 {
2788 mex_context = &context; 2824 mex_context = &context;
2789 2825
2801 cmex_fptr fcn = FCN_PTR_CAST (cmex_fptr, f); 2837 cmex_fptr fcn = FCN_PTR_CAST (cmex_fptr, f);
2802 2838
2803 fcn (nargout, argout, nargin, argin); 2839 fcn (nargout, argout, nargin, argin);
2804 } 2840 }
2805 } 2841 }
2806
2807 // Restore old mex pointer.
2808 unwind_protect::run ();
2809 2842
2810 // Convert returned array entries back into octave values. 2843 // Convert returned array entries back into octave values.
2811 2844
2812 octave_value_list retval; 2845 octave_value_list retval;
2813 2846
2830 } 2863 }
2831 } 2864 }
2832 } 2865 }
2833 2866
2834 // Clean up mex resources. 2867 // Clean up mex resources.
2835 unwind_protect::run (); 2868 unwind_protect::run_frame ("call_mex");
2836 2869
2837 return retval; 2870 return retval;
2838 } 2871 }
2839 2872
2840 octave_value_list 2873 octave_value_list
3154 { 3187 {
3155 if (mex_context) 3188 if (mex_context)
3156 { 3189 {
3157 const char *fname = mexFunctionName (); 3190 const char *fname = mexFunctionName ();
3158 3191
3159 if (mex_lock_count.find (fname) == mex_lock_count.end ()) 3192 std::map<std::string,int>::iterator p = mex_lock_count.find (fname);
3193
3194 if (p == mex_lock_count.end ())
3160 warning ("mexUnlock: funtion `%s' is not locked", fname); 3195 warning ("mexUnlock: funtion `%s' is not locked", fname);
3161 else 3196 else
3162 { 3197 {
3163 int count = --mex_lock_count[fname]; 3198 int count = --mex_lock_count[fname];
3164 3199
3165 if (count == 0) 3200 if (count == 0)
3166 { 3201 {
3167 munlock (fname); 3202 munlock (fname);
3168 3203
3169 mex_lock_count.erase (fname); 3204 mex_lock_count.erase (p);
3170 } 3205 }
3171 } 3206 }
3172 } 3207 }
3173 } 3208 }