Form fields are not displaying when error occurs in rails [on hold]

I have used Ajax call for creating Post. It displays form correctly when click button create post.it not shows fields when i only upload image without field values. i don’t know how it happens. when all fields are empty it shows validation error perfectly.like this,enter image description here

when i upload image without filling the field it ignores the field like this,enter image description here

and this is my posts_controller

    class PostsController < ApplicationController   before_action :set_topic   before_action :set_post, except: [:create, :new, :index]    def index     if params[:topic_id].to_i > 0       @posts = @topic.posts.all     else       @posts = Post.includes(:topic).references(:topic).all       @posts = @posts.order('topic desc')     end     @posts = @posts.eager_load(:ratings, :comments, :user, :users).paginate(page: params[:page], per_page: 10)     @tags = Tag.all   end    def show     @comment = @post.comments.new   end    def mark_as_read     @post.users << current_user unless @post.users.include?(current_user)   end    def new     @post = @topic.posts.new     @tags = Tag.all   end    def create     @post = @topic.posts.new(post_params)     @post.user_id = current_user.id     @posts = @topic.posts.paginate(page: params[:page], per_page: 10).eager_load(:user, :users, :comments, :ratings)     respond_to do |format|       if @post.save         format.js {render 'posts/create'}       elsif @post.image.save         format.js {render 'posts/new'}       else         format.js {render 'posts/new'}       end     end   end    def edit     authorize! :edit, @post     @tags = Tag.all   end    def update     params[:post][:tag_ids] ||= []     if @post.update(post_params)       redirect_to topic_post_path(@topic, @post), notice: 'Post was successfully updated.'     else       render :edit     end   end    def destroy     authorize! :destroy, @post     if @post.destroy       redirect_to topic_posts_path(@topic), notice: 'Post was successfully destroyed.'     else       render 'posts/show'     end   end    private    def set_topic     if params[:topic_id].present?       @topic = Topic.find(params[:topic_id])     end   end    def set_post     @post = @topic.posts.find(params[:id])   end    def post_params     params.require(:post).permit(:name, :description, :image, :topic_id, {tag_ids: []}, :tags_attributes => [:name])   end end 

And this is my _form.html.erb

    <%= form_for [@topic, @post], multipart: true, remote: true, authenticity_token: true do |form| %>   <% if @post.errors.any? %>     <div id="error_explanation">       <h2><%= pluralize(@post.errors.count, "error") %> prohibited this topic from being saved:</h2>       <ul>         <% @post.errors.full_messages.each do |message| %>           <li><%= message %></li>         <% end %>       </ul>     </div>   <% end %>   <%= form.text_field :name, placeholder: "Enter Post name", class: "form-control" %><br/>   <%= form.text_area :description, placeholder: "Enter Description", class: "form-control" %><br/>   <%= form.file_field :image, class: "form-control-file" %><br/>   <h3><strong>Select Tag</strong></h3>   <% @tags = Tag.all %>   <% if @tags %>     <% @tags.each do |tag| %>       <div>         <%= check_box_tag "post[tag_ids][]", tag.id, @post.tags.include?(tag) %>         <%= tag.name %>       </div>     <% end %>   <% end %>   <%= form.fields_for :tags, @post.tags.build do |f| %>     <%= f.text_field :name, placeholder: "Add Custom Tag" %>   <% end %>   <%= form.submit class: "btn btn-primary", data: {"disable-with": "Saving..."} %> <% end %> 

and this is my new.js.erb

$  ('#new-link').html("<%= j (render 'form') %>"); <% if @post.errors.any? %> alert("ERROR(S): <%= @post.errors.full_messages.join(',').html_safe %>") <% end %> 

and this is my create.js.erb

$  ('#new-link').hide(); alert("Post Created Successfully"); 

and this is the button i have used for render form

<div class="card-body">     <h5 class="card-title"><%= @topic.topic %></h5>     <div id="new-link">       <div id='ajax_loader' style="display: none;">         <%= image_tag '/assets/loader.gif' %>       </div>       <script>           $  (document).ajaxStop(function () {               $  ("#ajax_loader").hide();           });           $  (document).ajaxStart(function () {               $  ("#ajax_loader").show();           });       </script>       <%= link_to 'create Post', new_topic_post_path(@topic), class: "btn btn-primary", remote: true, data: {"disable-with": "Please wait..."} %>     </div>   </div> 

Checking if a shipping method exists

I am trying to create a custom WordPress/WooCommerce function in PHP. I am a newbie and would really appreciate some feedback on my code and how to improve the code! Right now it feels like there is a lot of duplication where there probably is a smarter and better way to do it.

Overall the function is used to hide shipping methods. Besides the usual shipping methods then some items is shipped in pallets by either quarter, half or full. When an item with shipping class of full pallet is in the cart, for example, it should hide all other shipping methods and so on.

// SHIPPING METHOD BASED ON SHIPPINGCLASS - FULL PALLET add_filter('woocommerce_package_rates', 'wtf_hide_shipping_method_based_on_shipping_class', 10, 2);  function wtf_hide_shipping_method_based_on_shipping_class($  available_shipping_methods, $  package) {     $  hide_when_shipping_class_exist = array(         171 => array(             'pakkelabels_shipping_gls_private',             'pakkelabels_shipping_postnord_private',             'pakkelabels_shipping_gls',             'pakkelabels_shipping_pdk',             'flat_rate:15',             'flat_rate:14'         )     );      $  hide_when_shipping_class_not_exist = array(         171 => array(             'flat_rate:12'         )     );       $  shipping_class_in_cart = array();     foreach(WC()->cart->get_cart_contents() as $  key => $  values) {        $  shipping_class_in_cart[] = $  values['data']->get_shipping_class_id();     }      foreach($  hide_when_shipping_class_exist as $  class_id => $  methods) {         if(in_array($  class_id, $  shipping_class_in_cart)){             foreach($  methods as & $  current_method) {                 unset($  available_shipping_methods[$  current_method]);             }         }     }     foreach($  hide_when_shipping_class_not_exist as $  class_id => $  methods) {         if(!in_array($  class_id, $  shipping_class_in_cart)){             foreach($  methods as & $  current_method) {                 unset($  available_shipping_methods[$  current_method]);             }         }     }     return $  available_shipping_methods; }  // SHIPPING METHOD BASED ON SHIPPINGCLASS - HALF PALLET add_filter('woocommerce_package_rates', 'wfe_hide_shipping_method_based_on_shipping_class', 10, 2);  function wfe_hide_shipping_method_based_on_shipping_class($  available_shipping_methods, $  package) {     $  hide_when_shipping_class_exist = array(         169 => array(             'pakkelabels_shipping_gls_private',             'pakkelabels_shipping_postnord_private',             'pakkelabels_shipping_gls',             'pakkelabels_shipping_pdk',             'flat_rate:15'         )     );      $  hide_when_shipping_class_not_exist = array(         169 => array(             'flat_rate:14'         )     );       $  shipping_class_in_cart = array();     foreach(WC()->cart->get_cart_contents() as $  key => $  values) {        $  shipping_class_in_cart[] = $  values['data']->get_shipping_class_id();     }      foreach($  hide_when_shipping_class_exist as $  class_id => $  methods) {         if(in_array($  class_id, $  shipping_class_in_cart)){             foreach($  methods as & $  current_method) {                 unset($  available_shipping_methods[$  current_method]);             }         }     }     foreach($  hide_when_shipping_class_not_exist as $  class_id => $  methods) {         if(!in_array($  class_id, $  shipping_class_in_cart)){             foreach($  methods as & $  current_method) {                 unset($  available_shipping_methods[$  current_method]);             }         }     }     return $  available_shipping_methods; }  // SHIPPING METHOD BASED ON SHIPPINGCLASS - QUARTER PALLET add_filter('woocommerce_package_rates', 'wf_hide_shipping_method_based_on_shipping_class', 10, 2);  function wf_hide_shipping_method_based_on_shipping_class($  available_shipping_methods, $  package) {     $  hide_when_shipping_class_exist = array(         211 => array(             'pakkelabels_shipping_gls_private',             'pakkelabels_shipping_postnord_private',             'pakkelabels_shipping_gls',             'pakkelabels_shipping_pdk',         )     );      $  hide_when_shipping_class_not_exist = array(         211 => array(             'flat_rate:15'         )     );       $  shipping_class_in_cart = array();     foreach(WC()->cart->get_cart_contents() as $  key => $  values) {        $  shipping_class_in_cart[] = $  values['data']->get_shipping_class_id();     }      foreach($  hide_when_shipping_class_exist as $  class_id => $  methods) {         if(in_array($  class_id, $  shipping_class_in_cart)){             foreach($  methods as & $  current_method) {                 unset($  available_shipping_methods[$  current_method]);             }         }     }     foreach($  hide_when_shipping_class_not_exist as $  class_id => $  methods) {         if(!in_array($  class_id, $  shipping_class_in_cart)){             foreach($  methods as & $  current_method) {                 unset($  available_shipping_methods[$  current_method]);             }         }     }     return $  available_shipping_methods; } 

HTML5 canvas video with React

I’m trying to work HTML5 canvas video into a React application while making the code as clean as possible. What kind of improvements should be made to improve the performance utilizing the React to its fullest potential?

import React, { Component } from 'react'; import './App.css'; import video from './video.mp4'; import watermark from './watermark.png';  class App extends Component { constructor() {     super();     this.state = {}; }  componentDidMount() {  const canvas = document.createElement('canvas'); canvas.width = 1280; canvas.height = 720; const context = canvas.getContext('2d'); context.drawImage(document.querySelector('video'), 0, 0, 720, 1280);                     context.drawImage(                         document.querySelector('.watermark'),                         parseInt(document.querySelector('select').value),                         parseInt(document.querySelector('select').value)                     );                     if (document.querySelector('input[name=live]').checked) {                         this.setState({ image: canvas.toDataURL() });                     }                 }   render() {     const range = [];     for (let i = 0; i < 1280; i++) {         range.push(i);     }      return (         <div className="app">               <video  src={video} controls />              <div>             <div className="watermarkButton" style={{}}>                  <span className="watermarkButtonX">Watermark X                 <select className="positionX">                     {range.map(i => (                         <option key={i}>{i}</option>                     ))} </select></span>                  <span className="watermarkButtonY">Watermark Y                 <select className="positionY">                     {range.map(i => (                         <option key={i}>{i}</option>                     ))} </select></span>                    <span>Live</span>                 <input type="checkbox" name="live" />                 </div>                   <button className = "watermarkButton watermarkSubmit"                     onClick={() => {                         const canvas = document.createElement('canvas');                         canvas.width = 1280;                         canvas.height = 720;                         const context = canvas.getContext('2d');                         context.drawImage(document.querySelector('video'), 0, 0, 1280, 720);                         context.drawImage(                             document.querySelector('.watermark'),                             parseInt(document.querySelector('.positionX').value),                             parseInt(document.querySelector('.positionY').value)                         );                         this.setState({ image: canvas.toDataURL() });                     }}> Watermark! </button>                   <img alt="watermarks" className="watermark" src={watermark} style={{ visibility: 'visible' }}  />                 <img alt="watermarks"   className="imageDisplay" height="405px" width="560px" src={this.state.image} />             </div>         </div>     );                 }              }  export default App; 

Building BFS with an implemented queue in C [on hold]

I’m implementing a graph traversal breadth-first search that I found here. However, their implementation involves integers and without any linked list. I was playing around with it a little bit I have no luck in getting any results because it doesn’t seem to work as intended.

This is the code that I currently have:

(main.c)

int main(void) {     t_graph *graph;     graph = create_graph(6);     add_edge(graph, 0, 1);     add_edge(graph, 0, 2);     add_edge(graph, 2, 4);     bfs(graph, 0);     return (0); } 

(bfs.c)

typedef struct      s_list {     struct s_list   *next;     void            *content;     size_t          content_size; }                   t_list;   typedef struct      s_queue {     t_list          *first;     t_list          *last; }                   t_queue;  t_queue             *init_queue(void); void                enqueue(t_queue *queue, void *content); void                *dequeue(t_queue *queue); void                *peek_queue(t_queue *queue); int                 is_empty(t_queue *queue); void                my_print_queue(t_queue *queue);  void                my_print_queue(t_queue *queue) {     if (is_empty(queue))         my_putstr("Empty queue\n");     else     {         while (!is_empty(queue))         {             my_putstr((char*)queue->first->content);             my_putstr(" ");             dequeue(queue);         }     } }  t_queue             *init_queue(void) {     t_queue         *node;     node = (t_queue *)my_memalloc(sizeof(t_queue));     node->first = NULL;     node->last = NULL;     return (node); }  void                enqueue(t_queue *queue, void *content) { t_list          *node;     node = (t_list *)my_memalloc(sizeof(t_list));     node->content = content;     node->next = NULL;     if (!queue->last)     {         queue->last = node;         queue->first = node;     }     else     {         queue->last->next = node;         queue->last = queue->last->next;     }     return ; }  void                *dequeue(t_queue *queue) {     t_list          *tmp;      tmp = queue->first;     if (!tmp)         return (NULL);     else     {         queue->first = tmp->next;         return (tmp->content);     }  }  void                *peek_queue(t_queue *queue) {     if (queue->first == NULL)         return (NULL);     return (queue->first->content); }  int                 is_empty(t_queue *queue) {     return (queue->first == NULL); }  t_node              *create_node(int val) {     t_node      *new_node;      new_node = (t_node*my_memalloc(sizeof(t_node));     new_node->vertex = val;     new_node->next = NULL;     return (new_node); }  t_graph             *create_graph(int vertices) {     int         i;     t_graph     *graph;      i = 0;     graph = my_memalloc(sizeof(t_graph));     graph->total_vertices = vertices;     printf("graph->total_vertices: %d\n", vertices);     graph->adj_lists = (t_node**)my_memalloc(sizeof(t_node));     graph->visited = my_memalloc(sizeof(int) * vertices);     while (i < vertices)     {         graph->adj_lists[i] = NULL;         graph->visited[i] = 0;         i++;     }     return (graph); }  void                add_edge(t_graph *graph, int src, int dst) {     t_node      *new_node;      new_node = create_node(dst);     new_node->next = graph->adj_lists[src];     graph->adj_lists[src] = new_node;      new_node = create_node(src);     new_node->next = graph->adj_lists[dst];     graph->adj_lists[dst] = new_node; }  void                bfs(t_graph *graph, int start_vertex) {     t_queue *queue;      queue = init_queue();     graph->visited[start_vertex] = 1;     enqueue(queue, &start_vertex);     while (!is_empty(queue))     {         my_print_queue(queue);         int current_vertex;         t_node *tmp;          current_vertex = (int)dequeue(queue);         printf("Visited %d\n", current_vertex);         tmp = graph->adj_lists[current_vertex];         while (tmp)         {             int adj_vertex;              adj_vertex = tmp->vertex;             if (graph->visited[adj_vertex] == 0)             {                 graph->visited[adj_vertex] = 1;                 enqueue(queue, &adj_vertex);             }             tmp = tmp->next;         }     } } 

I did some research like type-casting a void pointer to make it into a char or int, or any other data type. What happens is that the create graph does it’s creation after calling it; but, when it comes to the bfs, it doesn’t show the correct output after. I’m getting a result of

Visited: 0 

The expected output should be something like this:

Queue contains 0 Resetting queueVisited 0  Queue contains 2 1 Visited 2  Queue contains 1 4 Visited 1  Queue contains 4 Resetting queueVisited 4 

While posting this, I will keep debugging on my side and see what it does with couple printf statements.

Removing trailing whitespace from input lines

I’m going through the K&R C book (coming from Python) and am on exercise 1-18, which states:

Write a program to remove trailing blanks and tabs from each line of input, and to delete entirely blank lines.

I wasn’t able to find another solution online that looks quite like mine so I am questioning whether it is truly correct, even though it appears to work on anything I throw at it. I let an ending \n be whitespace, removed it and added a general newline to each printed output, but I’m not sure if that is cheating.

If there are any bad practices (or bugs in the code) for standard C please let me know.

#include <stdio.h>  #define MAXLINE 1000  int getli(char line[], int maxline);   main() {      int len;         int i;           char line[MAXLINE];       while ((len = getli(line, MAXLINE)) > 0) {         i = len-1;          /* replace any trailing whitespace character with null character */         while (line[i] == '\n' || line[i] == '\t' || line[i] == ' ') {             line[i] = '';             i--;         }          if (line[0] == '') {             printf("Blank line\n");         }          else printf("%s\n", line);     }      return 0; }  /* function to capture input line as char array */ int getli(char s[], int lim) {      int i, c;      for (i=0; i<lim-1 && (c=getchar()) != EOF && c != '\n'; i++) {         s[i] = c;     }      if (c == '\n') {         s[i] = c;         i++;     }      s[i] = '';     return i;  } 

Reverse String Java – Figuring out Complexity (Time & Space)

Been revamping on my coding puzzles practices…

What is the complexity (both time & space) for this method:

public static String reverse(String word) {      if (word == null || "".equals(word) || word.length() == 1) {         throw new IllegalArgumentException("Invalid Entry");     }      StringBuilder result = new StringBuilder();      for (int i=word.length() - 1; i >= 0; i--) {         result.append(word.charAt(i));     }      return result.toString();  } 

Is this a more optimized solution (what is the time & space complexity of this one as well):

public static String reverse ( String s ) {     int length = s.length(), last = length - 1;     char[] chars = s.toCharArray();     for ( int i = 0; i < length/2; i++ ) {         char c = chars[i];         chars[i] = chars[last - i];         chars[last - i] = c;     }     return new String(chars); } 

Know that there might be duplicate questions similar to this but am not asking for a solution, am only seeking how to figure out the two different types of complexities…

If someone has a better solution using Java, please post.

Pulsetrain generation with Verilog

I’m working with a PSoC device using Cypress’ turnkey toolchain, trying to generate a stream of pulses at intervals fed by the microntroller. I’ve given up trying to do this by drawing gates with the GUI and am writing my second Verilog program ever.

The spec is: pulses are described by a sequence of bytes; if the byte is 0x00..0x7f then wait that many ticks before generating the pulse; is 0x80 then wait 128 ticks and don’t generate a pulse. On each pulse, we trigger an interrupt which loads the next byte into the generator.

This should be trivial, but it’s behaving really weird…

module Sequencer (     output reg interrupt, // causes data to be updated     output reg wdata,     // goes to my consumer     input clock,          // tick counter     input [7:0] data,     // describes the current pulse     input reset           // what it says on the tin );  reg [6:0] counter;  always @(posedge clock) begin     if (reset)     begin         counter <= 0;         interrupt <= 0;         wdata <= 0;     end     else     begin         // This matches both pulses (00-7f) and spaces (80).         // For a space, the counter will roll over back to zero.         if (counter == data[6:0])         begin             counter <= 0;             interrupt <= 1;             wdata <= ~data[7]; // 0x80 means no pulse         end         else         begin             counter <= counter + 7'b1;             interrupt <= 0;             wdata <= 0;         end     end end  endmodule 

So, all the logic happens on the rising edge of the tick clock; my outputs are registered so they remain valid until the next rising edge, when I explicitly update them; my two outputs and the temporary counter are updated exactly once through every code path, so avoiding latches…

But what actually happens is that it works fine if my data bytes are in the 0x00-0x7f range, but as soon as I try to use 0x80 bytes, I get garbage out. (Although it’s hard to tell as my only way of testing is to record the pulses onto magnetic media, play them back, and sample with my first Verilog program ever…)

I feel that I’m just doing this wrong. So, what’s wrong?

Iterating through two objects with different structures in parallel

I have two objects, one input = Array<Type> and one stored = Array<{..., Type}>

What’s the best (cleanest) way to put the elements in the first array into the sub-elements of the second? We can assume they’re of the same size.

My current code below works, but looks bad due to the double iterator usage.

var count = 0; stored.forEach((obj)=> {     obj.value = input[count];     count++; }); 

Is there some sort of prototyping that I can use to shorten the code up?

Simple encryptor/decriptor, no GUI

I just made this simple XOR encryptor and decryptor (is not yet commented). It needs a file with the “private” key string inside.

usage: encryptor “file to encrypt/decrypt” “file with the private key” “output file”

To decrypt, just do the same but for the inputfile, use the already encrypted file and the same file with the key.

Can you review it please? Thank you!

Greetings!

#include <cstdio> static bool consoleOutput = false;  int Encrypt(const char* file_in, const char* keyFile_in, const char* file_out);  int main(int argc, char** argv) {     if(argc == 1)     {         printf("\nExecute with %s -h for more information\n", argv[0]);         return 0;     }     else if(argc == 2)     {         if((argv[1][0] == '-') && (argv[1][1] == 'h'))         {             printf("\nUso: %s \"in file\" \"file with key\" \"out file\"\n", argv[0]);             return 0;         }     }     Encrypt(argv[1], argv[2], argv[3]);      return 0; }  int Encrypt(const char* file_in, const char* keyFile_in, const char* file_out) {     FILE* mainFile = nullptr;     FILE* keyFile = nullptr;     FILE* outFile = nullptr;     char* inBuffer = nullptr;     char key[100];// = "mZq4t7w!";     int mainFileSize = 0;      mainFile = fopen(file_in, "rb");      if(mainFile == nullptr)     {         printf("Couldn't open file %s!", file_in);         return -1;     }      fseek(mainFile, 0, SEEK_END);     mainFileSize = ftell(mainFile);     rewind(mainFile);      if(mainFileSize <= 1)     {         printf("File is empty or the file is really small (not worthy)");         return -2;     }      inBuffer = new char[mainFileSize];      if(inBuffer == nullptr)     {         printf("Couldn't allocate %d bytes of memory", mainFileSize);         return -3;     }      fread(inBuffer,sizeof(char), mainFileSize, mainFile);      if(consoleOutput)     {         for(int i = 0; i < mainFileSize; i++)          {             putchar(inBuffer[i]);         }         puts("");     }      fclose(mainFile);      // read key file     keyFile = fopen(keyFile_in, "rb");     if(keyFile == nullptr)     {         printf("Couldn't open file %s!", keyFile_in);         return -1;     }      fseek(keyFile, 0, SEEK_END);     const int keyFileSize = ftell(keyFile);     rewind(keyFile);      fread(key, sizeof(char), keyFileSize, keyFile);      if(consoleOutput)     {         for(int i = 0; i < keyFileSize; i++)         {             putchar(key[i]);         }         printf("\nSize: %i", keyFileSize);     }      fclose(keyFile);      // output decryption/encryption     puts("\n\tStarting to do the magic\n");      for(int i = 0; i < mainFileSize; ++i)     {         inBuffer[i] = inBuffer[i] ^ key[i%keyFileSize-1];     }      if(consoleOutput)     {         for(int i = 0; i < mainFileSize; i++)         {             putchar(inBuffer[i]);         }         puts("");     }      // open output file     outFile = fopen(file_out, "wb");     if(outFile == nullptr)     {         printf("Couldn't open file %s!", file_out);         return -1;     }      fwrite(inBuffer, sizeof(char), mainFileSize, outFile);      fclose(outFile);      delete[] inBuffer;     puts("Finished!");      return 0; } 

c++ mutex implementation using windows apc

I just wrote this now and didn’t test it much this isn’t a replacement for std::mutex , but for something like fun I may develop it to make it shared across processes by storing the counters in a shared memory I don’t know whether it’s more efficient than the standard mutex or not also the apc callbacks could be used to implement condition variable or promise and future any advice will be welcome

void WINAPI wake_exclusive_locked_thread(ULONG_PTR inst)  { if (inst)     CloseHandle((void*)inst); }  class Mutex { volatile long long exclusive_locked; volatile unsigned long waiter_id; volatile long long shared_lock; public : Mutex(const Mutex&) = delete; Mutex(Mutex&&) = delete; Mutex& operator=(const Mutex&) = delete; Mutex& operator=(Mutex&&) = delete;  Mutex() : exclusive_locked(-1), waiter_id(0), shared_lock(0) { }  void lock() {     if (InterlockedIncrement64(&exclusive_locked) || InterlockedAdd64(&shared_lock,0))     {         unsigned long this_tid = cpp::this_thread::get_id();         unsigned long old_waiter_id = InterlockedExchange(&waiter_id, this_tid);  // put this thread at the front         InterlockedDecrement64(&exclusive_locked);          while (InterlockedIncrement64(&exclusive_locked) || InterlockedAdd64(&shared_lock, 0)) // if the lock is free the inc will return 0         {             InterlockedDecrement64(&exclusive_locked);             SleepEx(INFINITE, TRUE); // wait for the lock owner to unlock         }          InterlockedExchange(&waiter_id, old_waiter_id); // reback the old thread , may be null     }      // the thread now owns the lock }  void unlock() {     unsigned long current_waiter_id = InterlockedAdd((volatile LONG*)&waiter_id, 0);     InterlockedDecrement64(&exclusive_locked);     void *handle = OpenThread(THREAD_ALL_ACCESS, FALSE, current_waiter_id);     QueueUserAPC(wake_exclusive_locked_thread, handle, (ULONG_PTR)handle); }  void lock_shared() {      if (InterlockedAdd64(&exclusive_locked,0) > -1)     {         unsigned long this_tid = cpp::this_thread::get_id();         unsigned long old_waiter_id = InterlockedExchange(&waiter_id, this_tid); // put this thread at the front         while (InterlockedAdd64(&exclusive_locked, 0) > -1)         {             SleepEx(INFINITE, TRUE); // wait for the lock owner to unlock             void *handle = OpenThread(THREAD_ALL_ACCESS, FALSE, old_waiter_id); // notify the rest of the thrreads , if there is a write locker read lockers won't pass             QueueUserAPC(wake_exclusive_locked_thread, handle, (ULONG_PTR)handle);         }     }     InterlockedIncrement64(&shared_lock); }  void unlock_shared() {     unsigned long current_waiter_id = InterlockedAdd((volatile LONG*)&waiter_id, 0);     InterlockedDecrement64(&shared_lock);     void *handle = OpenThread(THREAD_ALL_ACCESS, FALSE, current_waiter_id);     QueueUserAPC(wake_exclusive_locked_thread, handle, (ULONG_PTR)handle); }  };