Mercurial > hg > octave-lojdl
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 } |